java笔记-多线程-线程通信


多线程间的通信:

//多线程间通信。
//功能:
//    1.Input类向资源中写入信息;
//    2.Output类从资源中读取信息;

//共享资源类;
class Res{
	String name;
	String sex;
}
//实现Runnable接口的类;
class Input implements Runnable{
	//定义共享资源的类参数,然后传递给构造函数;
	//目的是操作同一个共享资源的对象;
	Res r;
	Input(Res r){
		this.r=r;
	}
	//重写Runnable接口的run方法;
	public void run(){
		int x=0;
		while(true){
			//上锁;
			//由于操作同一资源,需和Output上的锁一致。
			//这样一旦上锁,另外一个操做共享资源的函数就不能操作共享数据。
			synchronized(Input.class){
				if(x==0){
					r.name="---a";
					r.sex="boy";
				}
				else{
					r.name="+++b";
					r.sex="girl";
				}
				x=(x+1)%2;
			}
			
		}
	}
}
class Output implements Runnable{
	Res r;
	Output(Res r){
		this.r=r;
	}
	public void run(){
		while(true){
			//上锁;
			//由于操作同一资源,需和Iuput上的锁一致。
			//这样一旦上锁,另外一个操做共享资源的函数就不能操作共享数据。
			synchronized(Input.class){
				System.out.println(r.name+"......"+r.sex);
			}
		}
	}
}
class InputOutputDemo{
	public static void main(String[] args){	
		Res r=new Res();
		//使两个线程操作同一对象。
		Output out=new Output(r);
		Input in=new Input(r);
		//构建两个线程,虽然是两个线程,但操作的是同一个对象中的共享资源。
		Thread t1=new Thread(in);
		Thread t2=new Thread(out);
		//启动线程。
		t1.start();
		t2.start();
	}
}

多线程的唤醒等待机制

//多线程间通信。
//功能:
//    1.Input类向资源中写入信息;
//    2.Output类从资源中读取信息;

//共享资源类;
class Res{
	String name;
	String sex;
	//定义读写操作完成标识。flag为真:有未读的数据,flag为假:数据已读
	boolean flag=false;
}
//实现Runnable接口的类;
class Input implements Runnable{
	//定义共享资源的类参数,然后传递给构造函数;
	//目的是操作同一个共享资源的对象;
	Res r;
	Input(Res r){
		this.r=r;
	}
	//重写Runnable接口的run方法;
	public void run(){
		int x=0;
		while(true){
			//上锁;
			//由于操作同一资源,需和Output上的锁一致。
			//这样一旦上锁,另外一个操做共享资源的函数就不能操作共享数据。
			synchronized(r){
				if(r.flag)	//若数据未读则等待。wait()定义时抛出异常。
					//调用wait方法将自身操作挂起,直到同一个对象上的锁以某种方式将其改变改变,并调用notify方法通知该代码块改变已经完成。
					try{r.wait();}catch(Exception e){}
				if(x==0){
					r.name="---a";
					r.sex="boy";
				}
				else{
					r.name="+++b";
					r.sex="girl";
				}
				x=(x+1)%2;
				//写完数据表明有数据未读,置未读标识符。
				r.flag=true;
				//notify()唤醒一个处于等待状态的线程。不能确切的唤醒特定的线程,
				//具体唤醒哪个线程由jvm决定,并且不是按照优先级。
				r.notify();
			}
			
		}
	}
}
class Output implements Runnable{
	Res r;
	Output(Res r){
		this.r=r;
	}
	public void run(){
		while(true){
			//上锁;
			//由于操作同一资源,需和Iuput上的锁一致。
			//这样一旦上锁,另外一个操做共享资源的函数就不能操作共享数据。
			synchronized(r){
				if(!r.flag){
					//么有未读数据则等待,直到另一线程存储了新的数据并唤醒该线程
					try{r.wait();}catch(Exception e){}
				}
				System.out.println(r.name+"......"+r.sex);
				//数据读取完毕,重置数据读取状态标识符。
				r.flag=false;
				//数据读取完毕,唤醒处于等待状态的线程。
				//notify()唤醒一个处于等待状态的线程。不能确切的唤醒特定的线程,
				//具体唤醒哪个线程由jvm决定,并且不是按照优先级。
				r.notify();
			}
		}
	}
}
class waitNotifyDemo{
	public static void main(String[] args){	
		Res r=new Res();
		//使两个线程操作同一对象。
		Output out=new Output(r);
		Input in=new Input(r);
		//构建两个线程,虽然是两个线程,但操作的是同一个对象中的共享资源。
		Thread t1=new Thread(in);
		Thread t2=new Thread(out);
		//启动线程。
		t1.start();
		t2.start();
	}
}
等待唤醒机制例程优化

//多线程间通信。
//功能:
//    1.Input类向资源中写入信息;
//    2.Output类从资源中读取信息;

//共享资源类;
class Res{
	private String name;
	private String sex;
	//定义读写操作完成标识。flag为真:有未读的数据,flag为假:数据已读
	private boolean flag=false;
	//设置共享资源数据
	//由于是对共享数据操作,需上锁。
	public synchronized void set(String name,String sex){
		if(this.flag){
			try{this.wait();}catch(Exception e){}
		}
		this.name=name;
		this.sex=sex;
		flag=true;
		//唤醒处于等待状态的线程,注意此处使用this。
		this.notify();
	}
	//输出共享资源数据
	//由于是对共享数据操作,需上锁。
	public synchronized void out(){
		//没有未读数据则等待。
		if(!this.flag){
			try{this.wait();}catch(Exception e){}
		}
		System.out.println(name+"......"+sex);
		flag=false;
		//唤醒处于等待状态的线程,注意此处使用this。
		this.notify();
	}
}
//实现Runnable接口的类;
class Input implements Runnable{
	//定义共享资源的类参数,然后传递给构造函数;
	//目的是操作同一个共享资源的对象;
	Res r;
	Input(Res r){
		this.r=r;
	}
	//重写Runnable接口的run方法;
	public void run(){
		int x=0;
		while(true){
			if(x==0){
				r.set("-----A","--boy");
			}
			else{
				r.set("+++++B","++girl");
			}
			x=(x+1)%2;
		}
	}
}
class Output implements Runnable{
	Res r;
	Output(Res r){
		this.r=r;
	}
	public void run(){
		while(true){
			r.out();
		}
	}
}
class OptimizeThread{
	public static void main(String[] args){	
		Res r=new Res();
		//使两个线程操作同一对象。
		new Thread(new Output(r)).start();
		new Thread(new Input(r)).start();
		
		/*
		Output out=new Output(r);
		Input in=new Input(r);
		//构建两个线程,虽然是两个线程,但操作的是同一个对象中的共享资源。
		Thread t1=new Thread(in);
		Thread t2=new Thread(out);
		//启动线程。
		t1.start();
		t2.start();
		*/
	}
}

生产者消费者实例

class Resource{
	private String name;
	private int count=1;
	private boolean flag;
	public synchronized void set(String name){
		//此处使用if语句只判断一次,当有多个线程进入if语句并处于等待状态时,
		//容易爆发安全隐患。改为while。
		//此处的notify唤醒的应该是out语句中的线程,但notify唤醒的线程较单一
		//改为notifyAll。
		while(flag){	//使进入该语句并处于等待状态的多个线程唤醒时都判断flag
			try{
				wait();
			}
			catch(Exception e){
			
			}
		}
		this.name=name+"......"+count++;//此处将商品名称自动加上商品编号。
		System.out.println("\t\t\t++++++product::"+this.name);
		flag=true;
		this.notify();
	}
	public synchronized void out(){
		//此处使用if语句只判断一次,当有多个线程进入if语句并处于等待状态时,
		//容易爆发安全隐患。改为while。
		//此处的notify唤醒的应该是set语句中的线程,但notify唤醒的线程较单一
		//改为notifyAll。
		while(!flag){	//使进入该语句并处于等待状态的多个线程唤醒时都判断flag
			try{
				wait();
			}
			catch(Exception e){
			
			}
		}
		System.out.println("------consumer::"+this.name);
		flag=false;
		this.notifyAll();
	}
}
class consumer implements Runnable{
	private Resource r;
	public void run(){
		while(true){
			r.out();
		}
	}
	consumer(Resource r){
		this.r=r;
	}
}
class product implements Runnable{
	private Resource r;
	public void run(){
		while(true){
			r.set("商品");
		}
	}
	product(Resource r){
		this.r=r;
	}
}
class ProConDemo{
	public static void main(String[] args){
		Resource r=new Resource();
		product pro=new product(r);
		consumer con=new consumer(r);
		Thread p1=new Thread(pro);
		Thread c1=new Thread(con);
		Thread p2=new Thread(pro);
		Thread c2=new Thread(con);
		Thread p3=new Thread(pro);
		Thread c3=new Thread(con);
		
		p1.start();
		c1.start();
		p2.start();
		c2.start();
		p3.start();
		c3.start();
	}
}

本方线程只唤醒对方线程

/*
** JDK1.5中提供了多线程的升级解决方案。
** 将同步synchronized替换成显式Lock操作。
** 将Object中的wait,notify,notifyAll替换为Condition对象。
** 该对象可以通过Lock锁对象的方法获取。
** 该对象可以调用awake(),signal(),signalAll().

** 该实例实现了:本方线程只唤醒对方线程的操作。
*/
import java.util.concurrent.locks.*;
class Resource{
	private String name;
	private int count=1;
	private boolean flag;
	//创建Lock对象。
	final Lock lock=new ReentrantLock();
	//通过Lock对象的方法创建Condition对象。
	final Condition condition_con=lock.newCondition();
	final Condition condition_pro=lock.newCondition();
	public void set(String name)throws InterruptedException{	//awake方法提示有异常抛出
		//直接上锁。
		lock.lock();
		try{
			while(flag){
				condition_pro.await();		//挂起本方线程。
			}
			this.name=name+"......"+count++;//此处将商品名称自动加上商品编号。
			System.out.println("\t\t\t++++++product::"+this.name);
			flag=true;
			condition_con.signal();			//唤醒对方线程。
		}
		//无论程序如何运行,最后都要解锁。
		finally{
			lock.unlock();				
		}
	}
	public void out(){
		//直接上锁。
		lock.lock();
		try{
			while(!flag){	//使进入该语句并处于等待状态的多个线程唤醒时都判断flag
				try{
					condition_con.await();	//挂起本方线程。
				}
				catch(Exception e){
			
				}
			}
			System.out.println("------consumer::"+this.name);
			flag=false;
			condition_pro.signal();			//唤醒对方线程。
		}
		//无论程序如何运行,最后都要解锁。
		finally{
			lock.unlock();
		}
	}
}
class consumer implements Runnable{
	private Resource r;
	public void run(){
		try{								//捕捉定义的out方法中的异常。
			while(true){
				r.out();
			}
		}
		catch(Exception e){
			
		}
	}
	consumer(Resource r){
		this.r=r;
	}
}
class product implements Runnable{
	private Resource r;
	public void run(){
		try{								//捕捉定义的set方法中的异常。
			while(true){
				r.set("商品");
			}
		}
		catch(Exception e){
		}
		
	}
	product(Resource r){
		this.r=r;
	}
}
class newLock{
	public static void main(String[] args){
		Resource r=new Resource();
		product pro=new product(r);
		consumer con=new consumer(r);
		Thread p1=new Thread(pro);
		Thread p2=new Thread(pro);
		Thread p3=new Thread(pro);
		Thread c1=new Thread(con);
		Thread c2=new Thread(con);
		Thread c3=new Thread(con);
		
		p1.start();
		p2.start();
		p3.start();
		c1.start();
		c2.start();
		c3.start();	
	}
}

中断线程

//线程的中断。
//线程的运行一般都是循环结构。只要构建中断循环标识就ok。
//对于上锁的线程,需要使用:对象.interrupt();来完成。
//interrupt激活冻结(等待)的线程。
class breakThread implements Runnable{
	//构建循环中断标识。
	public boolean flag=true;
	public synchronized void run(){
		while(flag){
			try{
				//线程一进入即进入冻结状态。
				wait();
			}
			//捕获中断异常标识,然后置循环中断标识。
			catch(InterruptedException e){
				System.out.println("Breaking Thread....");	
				flag=false;
			}
			System.out.println(Thread.currentThread().getName()+".....run.");
		}
		System.out.println("Thread Over.");
	}
	public void changeFlage(){
		flag=false;
	}
}
class StopThread{
	public static void main(String[] args){
		int num=0;
		breakThread bt=new breakThread();
		Thread t=new Thread(bt);
		t.start();
		
		while(true){
			if(++num==60){
				System.out.println("need to stop thread!");
				//num为60置线程中断,其实是激活冻结(等待)的线程。。
				t.interrupt();				
				break;
			}
			System.out.println("Main Thread run......"+num);
		}
	}
}

守护线程

//守护线程;
//当运行的线程全部为守护线程时,java虚拟机退出。
//守护线程可理解为守护前台线程,但前台线程结束,后台线程(守护线程)也就么有存在的必要了。
//守护线程开启必须在守护线程启动之前。
class breakThread implements Runnable{
	//构建循环中断标识。
	public boolean flag=true;
	public synchronized void run(){
		System.out.println(Thread.currentThread().getName()+".....run.");
	}
}
class StopThread{
	public static void main(String[] args){
		int num=0;
		breakThread bt=new breakThread();
		Thread t=new Thread(bt);
		//守护线程开启必须在线程启动之前。
		t.Daemon(true);
		t.start();
		
		while(true){
			if(++num==60){
				System.out.println("Stop main thread。");		
				//一旦main线程结束,只剩下t守护线程,java虚拟机退出。	
				break;
			}
			System.out.println("Main Thread run......"+num);
		}
	}
}

线程join方法

//join方法
//当A线程执行到了B线程的join方法时,A就会等待,等待B线程都执行完,A才会执行。
class Demo implements Runnable
{
	public void run(){
		for(int x=0;x<60;x++){
			System.out.println(Thread.currentThread().getName()+"....."+x);
		}		
	}
}
class joinDemo{
	public static void main(String[] args)throws Exception{
		Demo d=new Demo();
		Thread t1=new Thread(d);
		Thread t2=new Thread(d);
		
		t1.start();
		//加入join表明,t1线程申请获得cpu执行权,main线程暂时冻结。待t1线程执行完毕,main线程恢复。
		t1.join();
		t2.start();
		//若在t1,t2线程启动后执行t1.join(),则main线程冻结,t1和t2线程交替执行,main线程只等待t1线程结束后即恢复运行。
		
		for(int y=0;y<60;y++){
			System.out.println(Thread.currentThread().getName()+"..."+y);
		}
		System.out.println("Main thread over.");
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值