代码改变世界

java 多线程

2017-09-02 21:52  雄风狂飙  阅读(207)  评论(0编辑  收藏  举报

最近工作上有个地方需要用到多线程,是用C++的,下午加班改代码,但是网络出现问题,连不了主机,于是在java上面测试并回顾了一些知识。记录一下。

1.多线程的类helloworld。

在thread类中持有一个实现了runnable接口的实例化对象,然后thread类run的时候,会调用runnable的run。这一点在很多入门的书籍中都有介绍,没必要赘述,但是为什么要这么写,这里稍微把java中的代码粘贴一下。代码如下:

Thread类有一个接受runnable实现对象的构造函数,

public Thread(Runnable target) {
	init(null, target, "Thread-" + nextThreadNum(), 0);
    }

  init函数中最重要的一段代码是:this.target = target;

即给Thread的target这个变量set成了传进来的target。当Thread的run执行的时候,实际上会调用target的run函数。在源码中是这么说的“/**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.”

也就是Thread的start执行以后调用Thread的run方法。而run方法会调用target的run方法,代码如下:

public void run() {
	if (target != null) {
	    target.run();
	}
    }

  测试的Thread主类如下:

public class TestThread {
    
    static int threadNum = 10;
    static int maxloop = 10000; 
    
	public static void main(String arg[])
    {
        Thread threads[] = new Thread[100];

		for( int i = 0; i <= threadNum ; ++i)
        {
        	String threadName = "Thread " + Integer.valueOf(i);
        	threads[i] = new Thread(new TestRunable(threadName,maxloop));
        	threads[i].start();
        }
		
		for( int i = 0; i <= threadNum ; ++i)
        {
			try {
				threads[i].join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			System.out.println(Integer.valueOf(i) + "thread done.");
			
        }
		System.out.println( "count==" + Integer.valueOf( Global.count ) );
		
    }
}

  这里用到了一个全局变量Global.count,其目的在下面第三点说明。

2.测试join函数。join函数就是等待自身的函数,其效果如下:

8thread done.

。。。

Thread 9  9999
Thread 9  10000
9thread done.
10thread done.

也就是在线程8结束以后,线程9还未结束,那么主线程就一直等待线程9结束以后,再等待线程10结束,然后再继续往下执行。

3.测试线程操作统一个未上锁的变量的情况。

这里先把实现了runnable接口的类也贴出来。

package test;

public class TestRunable implements Runnable {
    
	private
		int mi;
	    String ms;
	    int mmaxloop;
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		
		for( int i = 0;i<=mmaxloop*10;++i  )
		{
		    System.out.println( ms + "  " + Integer.valueOf(mi));
		    ++mi;
		    ++Global.count;
		}
	}
    
	TestRunable(String ss,int maxLoop)
	{
		this.mi = 0;	
		this.ms = ss;
		mmaxloop = maxLoop;
	}
}

  此外,还有全局变量的类也一道贴出来:

public class Global {
	public
    static int count = 0;
}

  其结果是每次测试的结果,对全局变量的打印数字都不一致。

比如,某次执行的结果是(对源码中的某些数字可能进行一些放大或者缩小,不影响其效果): 

7thread done.
8thread done.
9thread done.
10thread done.
count==1100010

另外一次执行的结果是:

7thread done.
8thread done.
9thread done.
10thread done.
count==1100011

4.互斥实现。

 testRunnable类的代码修改为:

for( int i = 0;i<=mmaxloop*100;++i  )
		{
		    System.out.println( ms + "  " + Integer.valueOf(mi));
		    ++mi;
		    synchronized(this)
		    {
		        ++Global.count;
		    }
		}

  再执行多次,查看Global.count结果,都是一个值吗?

第一次:

count==1100009

第二次:

8thread done.
9thread done.
10thread done.
count==1100011

于是,发现根本就没有完成互斥。

5.原来互斥是需要针对一个对象的。经过修改以后的代码如下,就可以完成互斥了。

static int threadNum = 10;
    static int maxloop = 1000; 
    
	public static void main(String arg[]) {
		Thread threads[] = new Thread[100];
		System.out.println("ssssssssssss");
		Global global = new Global();
		String threadName = "same";
		TestRunnable testRunnable = new TestRunnable(threadName, maxloop,
				global);
		for (int i = 0; i <= threadNum; ++i) {
			// String threadName = "Thread " + Integer.valueOf(i);
			threads[i] = new Thread(testRunnable);
			threads[i].start();
		}

		for (int i = 0; i <= threadNum; ++i) {
			try {
				threads[i].join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			// System.out.println(Integer.valueOf(i) + "thread done. mi==" +
			// Integer.valueOf(threads[i].g));

			System.out.println(Integer.valueOf(i)
					+ "thread done. global.count=="
					+ Integer.valueOf(global.count));

		}
		System.out.println("count==" + Integer.valueOf(global.count));

	}

  results:

count==1100000

执行多次都是一个结果。