黑马程序员 java 基础 毕向东 面向对象 多线程 通信 优化 jdk 1.5 之后新特性Lock

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

黑马程序员 java 基础 毕向东 面向对象 多线程 通信 优化 jdk 1.5 之后新特性Lock

1 线程通信:synchronized 实现 、Object o 作为锁  wait notify notifyAll 应用场景

package day12Thread;
/*
 * 线程间通信
 * 其实是多个线程在操作同一个资源
 * 但是操作的动作不同
 * 
 * 等待 唤醒机制 
 * 
 * wait()
 * nitify()
 * notifyAll() 
 * 都使用在同步中。
 * 因为要对持有监视器(锁)的线程操作
 * 所以要使用在同步中,只有同步才具有锁
 * 为什么这些操作要定义在Object类中
 * 因为这些方法在操作同步线程中,都必须
 * 标示他们所操作线程中的锁
 * 只有同一个锁上的被等待线程,
 * 可以被同一个锁上的notify 唤醒
 * 不可以对不同锁上的线程进行唤醒
 * 
 * 也就是说,等待唤醒的线程必须是同一个锁上
 * 而锁可以是任意对象,所以可以被任意对象调用的方法定义在
 * Object类
 * 
 * */
class Res{
	String name;
	String sex;
	boolean rw=false;
}
class Input implements Runnable{
	Res res;
	public Input(Res res) {
		this.res=res;
	}
	public void run() {
		boolean flag=true;
		while (true) {
			synchronized (res) {
				if(res.rw)
					try {
						res.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				if (flag) {
					res.name="mike";
					res.sex="man";
				}else {
					res.name="丽丽";
					res.sex="女";
				}
				flag=flag==true?false:true;
				res.rw=true;
				res.notify();
			}
		}
	}
}
class Output implements Runnable{
	Res res;
	public Output(Res res) {
		this.res=res;
	}
	public void run() {
		while (true) {
			synchronized (res) {
				if(!res.rw)
					try {
						res.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				System.out.println(res.name+"-"+res.sex);
				res.rw=false;
				res.notify();
			}
		}
	}
}
public class InputOutputDemo {
	public static void main(String[] args) {
		Res res=new Res();
		Input input=new  Input(res);
		Output output=new Output(res);
		Thread threadIn=new Thread(input);
		Thread threadOut=new Thread(output);
		threadIn.start();
		threadOut.start();
	}

}

2 在上面例子上的优化  


package day12Thread;
/*
 * 线程间通信
 * 其实是多个线程在操作同一个资源
 * 但是操作的动作不同
 * 
 * 等待 唤醒机制 
 * 
 * wait()
 * nitify()
 * notifyAll() 
 * 都使用在同步中。
 * 因为要对持有监视器(锁)的线程操作
 * 所以要使用在同步中,只有同步才具有锁
 * 为什么这些操作要定义在Object类中
 * 因为这些方法在操作同步线程中,都必须
 * 标示他们所操作线程中的锁
 * 只有同一个锁上的被等待线程,
 * 可以被同一个锁上的notify 唤醒
 * 不可以对不同锁上的线程进行唤醒
 * 
 * 也就是说,等待唤醒的线程必须是同一个锁上
 * 而锁可以是任意对象,所以可以被任意对象调用的方法定义在
 * Object类中
 * 
 * ------------------------------代码优化-----------------------------------
 * */
class Res2{
	private String name;
	private String sex;
	private boolean rw=false;
	public synchronized void setNameSex(String name,String sex) {
		if (rw) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.name = name;
		this.sex = sex;
		rw=true;
		this.notify();
	}
	public synchronized void getSexName() {
		if (!rw) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(name+"---"+sex);
		rw=false;
		this.notify();
	}


}
class Input2 implements Runnable{
	Res2 res;
	public Input2(Res2 res) {
		this.res=res;
	}
	public void run() {
		boolean flag=true;
		while (true) {
			
				if (flag) {
					res.setNameSex("mike","man");
				}else {
					res.setNameSex("丽丽","女");
				}
				flag=flag==true?false:true;
			}
		}
}
class Output2 implements Runnable{
	Res2 res;
	public Output2(Res2 res) {
		this.res=res;
	}
	public void run() {
		while (true) {
				res.getSexName();
			}
		}
}
public class InputOutputDemo2 {
	public static void main(String[] args) {
		Res2 res=new Res2();
//		Input2 input=new  Input2(res);
//		Output2 output=new Output2(res);
//		Thread threadIn=new Thread(input);
//		Thread threadOut=new Thread(output);
//		threadIn.start();
//		threadOut.start();
		new Thread(new  Input2(res)).start();
		new Thread(new Output2(res)).start();
		
	}


}

3 多个生成者线程 和 多个消费者线程  、notify  和 notifyAll 的区别


package day12Thread;
/*对于多个生产者和消费者
 * 为什么要定义while 判断标记
 * 原因:为了让被唤醒的线程再一次判断标记
 * 
 * 为什么定义notifyAll()
 * 因为需要唤醒对方线程
 * 因为只用notify ,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待
 * */
public class ProduceConsumeDemo {

	public static void main(String[] args) {
		Resource resource=new Resource();
		Produce produce=new Produce(resource);
		Consume consume=new Consume(resource);
		
		Thread threadPro1=new Thread(produce);
		Thread threadPro2=new Thread(produce);
		Thread threadConsumee1=new Thread(consume);
		Thread threadConsumee2=new Thread(consume);
		threadPro1.start();
		threadPro2.start();
		threadConsumee1.start();
		threadConsumee2.start();
	}

}
class Produce implements Runnable{
	private Resource resource;
	public Produce(Resource resource) {
		this.resource=resource;
	}
	public synchronized void run() {
		while (true) {
			resource.set("+商品+");
		}
	}
}
class Consume implements Runnable{
	private Resource resource;
	public Consume(Resource resource) {
		this.resource=resource;
	}
	public synchronized void run() {
		while (true) {
			resource.out();
		}
	}
	
}
class Resource{
	private String name;
	private int count =1;
	private boolean flag=false;
	public synchronized void set (String name){
//		if(flag){   因为多个生成多个消费 线程 唤醒后没有重新判断,所以会出现线程全部等待
		while(flag){ 
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.name=name+"--"+count++;
		System.out.println(Thread.currentThread().getName()+"--生产者--"+this.name);
		flag=true;
//		this.notify();//会唤醒线程池中最早等待的线程
		this.notifyAll();//唤醒线程池中所有等待的线程。唤醒对方线程
	}
	public synchronized void out() {
		while(!flag){
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName()+"----消费者----"+this.name);
		flag=false;
		this.notifyAll();
	}
}

4使用java 新特性 Lock 代替synchronized 实现同步和线程通信。
将 Object 中的 wait notify notifyAll 替换了Condition 对象,实现了本方只唤醒对方线程操作



package day12Thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*对于多个生产者和消费者
 * 为什么要定义while 判断标记
 * 原因:为了让被唤醒的线程再一次判断标记
 * 
 * 为什么定义notifyAll()
 * 因为需要唤醒对方线程
 * 因为只用notify ,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待
 * 
 * 
 * jdk 1.5 中国提供了多线程升级解决方案
 * 将同步 的synchronized替换成Lock操作
 * 将 Object 中的 wait  notify   notifyAll 替换了Condition  对象
 * 该对象可以Lock锁进行获取
 * 在该例子中,实现了本方只唤醒对方线程操作
 * */
public class ProduceConsumeLockDemo {

	public static void main(String[] args) {
		Resource2 resource=new Resource2();
		Produce2 produce=new Produce2(resource);
		Consume2 consume=new Consume2(resource);
		
		Thread threadPro1=new Thread(produce);
		Thread threadPro2=new Thread(produce);
		Thread threadConsume2e1=new Thread(consume);
		Thread threadConsume2e2=new Thread(consume);
		threadPro1.start();
		threadPro2.start();
		threadConsume2e1.start();
		threadConsume2e2.start();
	}

}
class Produce2 implements Runnable{
	private Resource2 resource;
	public Produce2(Resource2 resource) {
		this.resource=resource;
	}
	public  void run() {
		while (true) {
			try {
				resource.set("+商品+");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
class Consume2 implements Runnable{
	private Resource2 resource;
	public Consume2(Resource2 resource) {
		this.resource=resource;
	}
	public  void run() {
		while (true) {
			try {
				resource.out();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
}
class Resource2{
	private String name;
	private int count =1;
	private boolean flag=false;
	//---------------------------------------------------------
	private Lock lock =new ReentrantLock();
	private Condition con_Produce=lock.newCondition();
	private Condition con_Consume=lock.newCondition();
	//---------------------------------------------------------
	public  void set (String name)throws InterruptedException {
		lock.lock();//----------------------- 
			try {
				while(flag){ 
//					con.await();
					con_Produce.await();
				}
				this.name=name+"--"+count++;
				System.out.println(Thread.currentThread().getName()+"--生产者--"+this.name);
				flag=true;
//				con.signal();
//				con.signalAll();//还是唤醒了所有线程
				con_Consume.signal();
			}finally{
				lock.unlock();//--------------
				//释放锁的动作一定要执行
			}
	}
	public  void out() throws InterruptedException{
		lock.lock();//进来,先拿到锁
		try {
			while(!flag){
				con_Consume.await();
			}
			System.out.println(Thread.currentThread().getName()+"----消费者----"+this.name);
			flag=false;
//			con.signal();
			con_Produce.signal();
		}finally{
			lock.unlock();
		}
		
	}
}


5 Thread 的stop()  interrup ()方法  已经 守护线程/用户线程  简介

package day12Thread;
/*
 * stop 方法以及过时
 * 如何停止线程
 * 只有一种方法 run 方法 运行结束
 * 
 * 开启多线程运行,运行代码通常是循环结构
 * 只要控制住循环,就可以让run方法结束,也就是线程结束
 * 
 * 特殊情况
 * 当线程处于冻结状态,就不会读到标记
 * 那么线程就不会结束
 * 
 * interrupt 强制将冻结状态的线程 运行起来  
 * 当没有指定的方式让冻结的线程回复都爱运行状态时
 * 
 * 这时需要对冻结状态进行清除
 * 强制让线程恢复到运行状态中来,就可以操作标记你,让线程结束
 * Thread类 interrupt 提供了该功能
 * 
 * 守护线程 或者 用户线程
 * 
 * 标记为后台线程  :
 * 处理结束和普通线程有区别外,其他都一样
 * 当所有前台线程都结束后,后台线程自动结束(有依赖的意思)
 * 主线程是前台线程。
 * 当正在运行的线程都是守护线程是。jvm自动停止
 * */
public class StopThreadDemo {
	public static void main(String[] args) {
		StopThread st=new StopThread();
		Thread t1=new Thread(st);
		Thread t2=new Thread(st);
		t1.setDaemon(true);
		t2.setDaemon(true);
		t1.start();
		t2.start();
		
		int num=0;
		while (true) {
			if (num++==60) {
//				st.changFlag();
//				t1.interrupt();
//				t2.interrupt();
				break;
			}
			System.out.println(Thread.currentThread().getName()+"main -"+num);
		}
		System.out.println("over");
	}
}
class StopThread implements Runnable{
	private boolean flag=true;
	public synchronized void run() {
		while(flag){
			try {
				wait();
			} catch (InterruptedException e) {
//				e.printStackTrace();
				System.out.println(Thread.currentThread().getName()+"----InterruptedException");
				flag=false;
			}
			System.out.println(Thread.currentThread().getName()+"----run");
		}
	}
	public void changFlag(){
		flag=false;
	}
}

6  Thread  的join ()方法简介

package day12Thread;

/*
 * 当 A线程执行到了 B线程的Join方法时
 * A线程就会等待B线程终止,A才会 执行
 * join可以用来临时加入线程执行
 * 
 * Thread[Thread-0,5,main]--- run29
Thread[Thread-1,5,main]--- run32
Thread[Thread-0,5,main]--- run30
Thread【线程名,优先级,线程组】 一般谁开启了线程,线程属于哪个组
优先级 代表 使用cpu 的使用频率
默认优先级是  5
优先级 分 1 ----10 级
static int MAX_PRIORITY     10
          线程可以具有的最高优先级。 
static int MIN_PRIORITY     1
          线程可以具有的最低优先级。 
static int NORM_PRIORITY    5
          分配给线程的默认优先级。 

 * */
public class ClassJoinDemo  {
	public static void main(String[] args) throws Exception {
		JoinDmeo joinDmeo=new JoinDmeo();
		Thread thread1=new Thread(joinDmeo);
		Thread thread2=new Thread(joinDmeo);
		
		thread1.start();
//		thread1.setPriority(Thread.MAX_PRIORITY);
		
//		thread1.join();
		/*thread1.join();
		 * thread1 请求执行权
		 * 主线程处于冻结状态
		 * thread1 结束后 主线程才恢复到运行状态
		 * 等待这个线程 终止
		 * 当进行多线程运行时,
		 * 临时加入一个线程,让这个线程运算完,
		 * */
		thread2.start();
//		thread1.join();
		for (int i = 0; i < 80; i++) {
			System.out.println("mian "+i);
		}
		System.out.println("mina over");
	}

}
class JoinDmeo implements Runnable{
	public void run() {
		for (int i = 0; i < 70; i++) {
			System.out.println(Thread.currentThread().toString()+"--- run"+i);
			Thread.yield();//  释放执行权
		}
	}
	
}

7  使用多线程的情景简单示例

package day12Thread;
/**/
public class ThreadTest {
	public static void main(String[] args) {
		new Thread(){
			public void run(){
				for (int i = 0; i < 100; i++) {
					System.out.println(Thread.currentThread().getName()+"------"+i);
				}
			}
		}.start();
		for (int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName()+"------"+i);
		}
		Runnable runnable=new Runnable() {
			
			@Override
			public void run() {
				for (int i = 0; i < 100; i++) {
					System.out.println(Thread.currentThread().getName()+"------"+i);
				}
			}
		};
		new Thread(runnable).start();
	}

}

//class Test1 extends Thread{
//	public void run() {
//		for (int i = 0; i < 100; i++) {
//			System.out.println(Thread.currentThread().getName()+"------"+i);
//		}
//	}
//}

《传智播客_毕向东_Java基础视频教程\黑马程序员_毕向东_Java基础视频教程第12天 多线程 通信 优化 jdk 1.5 之后新特性Lock》

该天内容介绍了java 多线程中 的多线程通信机制,线程间唤醒、中断、同步机制,

学习了java中多线程的具体实现操作。


你可能感兴趣的:(黑马程序员 java 基础 毕向东 面向对象 多线程 通信 优化 jdk 1.5 之后新特性Lock)