java编程笔记21 线程

1,两种方法来创建线程:

1)继承Thread类实现run方法:

public class Hello1 extends Thread
{
	String name;
	
	public Hello1(String n)
	{
		name = n;
	}
	
	public void run()
	{
		for (int i=1; i<=10; i++)
		{
			System.out.println(name+" Hello "+i);
		}
	}
}

2)实现Runnable接口,实现run方法:

public class Hello2 implements Runnable
{
	String name;
	
	public Hello2(String n)
	{
		name = n;
	}
	
	public void run()
	{
		for (int i=1; i<=10; i++)
			System.out.println(name+" Hello "+i);
	}
}

推荐第二种方法;

2,产生Thread对象和启动线程

public class ThreadsExample1
{
	public static void main(String argv[])
	{
		Hello1 h1 = new Hello1("Thread1");
		Hello2 h2 = new Hello2("Thread2");
		
		Thread t1 = new Thread(h1);
		Thread t2 = new Thread(h2);
		
		t1.start();
		t2.start();
	}
}

3,停止线程运行

下面的run方法可以让线程一直运行:

public class Hello3 implements Runnable
{
	String name;
	
	public Hello3(String n)
	{
		name = n;
	}
	
	public void run()
	{
		int i=0;
		
		while(true)//这样来写run方法
		{
			i++;
			System.out.println(name+" Hello "+i);
		}
	}
}

加一个循环条件来达到停止现成的效果:

public class Hello4 implements Runnable
{
	String name;
	Boolean isStop;
	public Hello4(String n)
	{
		name = n;
		isStop = false;
	}
	
	public void run()
	{
		int i=0;
		
		while(!isStop)
		{
			i++;
			System.out.println(name+" Hello "+i);
		}
	}
	
	public void stop()//控制条件
	{
		isStop = true;
	}
}

当一个线程对象进入死亡状态后,就没有任何方法可以回到其他状态。

4,暂停线程运行

sleep方法:

yield方法

join方法,

来看join的一个例子:

MotherThread:
package ch22;

public class MotherThread implements Runnable
{
	public void run()
	{
		System.out.println("妈妈准备煮饭");
		System.out.println("妈妈发现米酒用完了");
		System.out.println("妈妈叫儿子去买米酒");
		
		Thread son = new Thread(new SonThread());
		son.start();
		
		System.out.println("妈妈等待儿子把米酒买回来");
		
		try {
			son.join();
		}
		catch (InterruptedException ie)
		{
			System.err.println("发生异常!");
			System.err.println("妈妈中断煮饭");
			System.exit(1);
		}
		
		System.out.println("妈妈开始煮饭");
		System.out.println("妈妈煮好饭了");
	}
}

SonThread:

package ch22;

public class SonThread implements Runnable
{ 
	public void run()
	{
		System.out.println("儿子出门去买米酒");
		System.out.println("儿子买东西来回需5分钟");
		
		try { 
			for (int i=1; i<=5; i++)
			{
				Thread.sleep(1000);
				System.out.print(i+"分钟 ");
			}
		}
		catch (InterruptedException ie)
		{
			System.err.println("儿子发生意外");
		}
		
		System.out.println("\n儿子买米酒回来了");
	}		
}

Cooking:
package ch22;

public class Cooking
{
	public static void main(String argv[])
	{
		Thread mother = new Thread(new MotherThread());
		mother.start();
	}
}

运行结果:

5,数据同步处理

现在我们有这样一个线程:

package ch22;

public class ShareData implements Runnable
{
	int i;

	public void run()
	{
		while (i<10)
		{
			i++;
			for(int j=0; j<10000000; j++);
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
	}
}

现在我们来产生两个ShareData对象,并给两个Thread运行

package ch22;

public class ThreadsExample2
{
	public static void main(String argv[])
	{
		ShareData s1 = new ShareData();
		ShareData s2 = new ShareData();
		
		Thread t1 = new Thread(s1);
		Thread t2 = new Thread(s2);
		
		t1.start();
		t2.start();
	}
}

其结果如图:

可以看到,两个Thread对象在交互运行,Thread 0和Thread 1分别从0按顺序到10.

这是因为两个Thread共用了程序代码但是没有共用数据,下面我们来看程序代码和数据都共用的效果

package ch22;

public class ThreadsExample3
{
	public static void main(String argv[])
	{
		ShareData s = new ShareData();
		Thread t1 = new Thread(s);//两个小成共用一个对象ShareData
		Thread t2 = new Thread(s);
		
		t1.start();
		t2.start();
	}
}

结果并不是你所想象的从0到10,而是:

这是为什么呢????

这是因为线程被分割运行了,具体分析略。

6,synchronized实现线程同步

synchronized(要取得锁的对象)

{

  要锁定的代码

}

package ch22;

public class SyncShareData implements Runnable
{
	int i;
	
	public void run()
	{
		while (i<10)
		{
			/*锁的对象是SyncShareData自己,也就是说这个对象对应的线程要进行同步机制*/
			synchronized(this)
			{
				i++;
				for(int j=0; j<10000000; j++);
				System.out.println(Thread.currentThread().getName()+":"+i);
			}
		}
	}
}

package ch22;

public class ThreadsExample4
{
	public static void main(String argv[])
	{
		SyncShareData s = new SyncShareData();
		/*t1和t2都是操作同一个SyncShareData对象的线程,
		 * 要进行同步机制,因为SyncShareData实现了锁机制*/
		Thread t1 = new Thread(s);
		Thread t2 = new Thread(s);
		
		t1.start();
		t2.start();
	}
}

实现了两个线程对同一个对象操作的同步

7,等待wait与通报notify

生产者和消费者的例子:

package ch22;

public class Storage
{
	private int count;//当前库存值
	private int size;//最大库存量
	
	public Storage(int s)
	{
		size = s;
	}
	
	
	//类里的方法实现了锁,则调用这个方法必须取得这个类的对象的锁
	public synchronized void addData(String n)
	{
		while (count == size)//注意为什么要用while循环而不是if
		{
			try {
				this.wait();//进入等待状态
			}
			catch (InterruptedException e) { }
		}
		
		this.notify();//通知消费者可以消费了
		count++;
		System.out.println(n+" make data count: "+count);
	}
	
	
	public synchronized void delData(String n)
	{
		while (count == 0)
		{
			try {
				this.wait();
			}
			catch (InterruptedException e) { }
		}
		
		this.notify();
		System.out.println(n+" use data count: "+count);
		count--;
	}	
}

package ch22;

public class Producer extends Thread
{
	private String name;
	private Storage s;
	
	public Producer(String n, Storage s)
	{
		name = n;
		this.s = s;
	}
	
	public void run()
	{
		while (true)
		{
			s.addData(name);

			try {
				sleep((int)Math.random()*3000);
			}
			catch (InterruptedException e) { } 
		}
	}
}

package ch22;

public class Consumer extends Thread
{
	private String name;
	private Storage s;
	
	public Consumer(String n, Storage s)
	{
		name = n;
		this.s = s;
	}
	
	public void run()
	{
		while (true)
		{
			s.delData(name);
			
			try {
				sleep((int)Math.random()*3000);
			}
			catch (InterruptedException e) { } 
		}
	}
}

package ch22;

public class ThreadsExample5
{
	public static void main(String argv[])
	{
		Storage s = new Storage(3);
		Producer p1 = new Producer("Producer1", s);
		Producer p2 = new Producer("Producer2", s);
		Consumer c1 = new Consumer("Consumer1", s);
		
		p1.start();
		p2.start();
		c1.start();
		
	}
}

.........

Producer1 make data count: 3
Consumer1 use data count: 3
Consumer1 use data count: 2
Producer1 make data count: 2
Consumer1 use data count: 2
Producer1 make data count: 2

.........

posted @ 2011-03-21 21:48  jinmengzhe  阅读(461)  评论(0编辑  收藏  举报