1.线程间通讯:
多个线程在处理同一资源,但是任务却不同。

2.等待唤醒机制:
涉及的方法:

1.wait()  让线程处于冻结状态,被wait的线程会被存储到线程池。通过锁来区分线程池(等待集)
2.notify()  唤醒线程池中的一个线程 (任意)。处于运行或者临时阻塞状态,即获得执行资格
3.notifyAll()   唤醒线程池中的所有线程。这些方法必须定义在同步中,
因为这些方法是用于操作线程状态的方法,必须要明确到底操作的是哪个锁上的线程。
为什么操作线程的方法wait,notify,notifyall 定义在了object类中?因为这些方法是监视器的方法。监视器就是锁。
锁可以是任意对象,任意对象调用的方法一定定义在object类中。

图解:

代码:

class Resource
{String name;String sex;boolean flag = false;
}class Input implements Runnable
{private Resource r;Input(Resource r){this.r = r;}public void run(){int x = 0;while(true){synchronized(r){x = ++x%2;if(r.flag)try{r.wait();}catch (Exception e){}if(x == 0){r.name = "小美";r.sex = "女";}else{r.name = "王五";r.sex = "男";}r.flag = true;  r.notify();}}       }
}class Output implements Runnable
{   private Resource r;Output(Resource r){this.r = r;}public void run(){while(true){synchronized(r){if(!r.flag)try{r.wait();   //说明是哪个锁调用wait()。对象锁也称对象监视器,而wait就是操作对象监视器上的线程。}catch (Exception e){}if(r!=null) System.out.println(r.name + "....." + r.sex);   r.flag = false;r.notify();  //说明是哪个锁调用notify()}}}}class  ResourceDemo
{public static void main(String[] args) {Resource r = new Resource();   //c创建资源Input in = new Input(r);    //创建人物Output out = new Output(r);   Thread t1 = new Thread(in);    //创建线程,执行路径Thread t2 = new Thread(out);t1.start();      //开启线程t2.start();}
}

3.等待唤醒 代码 开发优化:

class Resource
{private String name;private String sex;private boolean flag = false;public synchronized  void set(String name, String sex)   //已经解决name,sex同步问题{if(flag)try{this.wait();}catch (Exception e){}this.name = name;    this.sex =sex;flag = true;notify();}public synchronized void out(){if(!flag)try{wait(); }catch (Exception e){}if(this!=null)  System.out.println(name + "....." + sex);   flag = false;notify();}
}class Input implements Runnable
{private Resource r;Input(Resource r){this.r = r;}public void run(){int x = 0;while(true){if(x == 0){r.set("xiaoni","女");}else{r.set("王五","男");}   x = ++x%2;}}
}class Output implements Runnable
{   private Resource r;Output(Resource r){this.r = r;}public void run(){while(true){r.out();}}
}class  ResourceDemo
{public static void main(String[] args) {Resource r = new Resource();   //c创建资源Input in = new Input(r);    //创建人物Output out = new Output(r);   Thread t1 = new Thread(in);    //创建线程,执行路径Thread t2 = new Thread(out);t1.start();      //开启线程t2.start();}
}

4.多生产者多消费者 问题:

两个关键点:
1.判断标记的循环:
应该用while,始终判断标记。但是可能会造成全部等待,产生死锁。2.所以,为了避免死锁,应该使用全部唤醒notifyall(),这样可以唤醒对方线程,解决死锁问题。if判断标记,只有一次,会导致不该运行的线程运行了。出现数据错误的情况。
while判断标记,解决了线程获取执行权后,是否要运行。
notify:只能唤醒一个线程,如果本方唤醒了本方,没有意义。而且while判断标记+notify会导致死锁。
notifyAll:解决了,本方线程一定会唤醒对方线程的问题。但是全部唤醒效率低。JDK1.5新工具解决办法:接口 Lock,接口Condition

接口 Lock:
它替代了同步代码块或者同步函数。将同步的隐式锁操作变成显示锁操作。同时更为灵活。可以一个锁上加上多组监视器。
lock() : 获取锁
unlock() : 释放锁,通常定义在finally代码块中。

Lock lock = new ReentrantLock(); //互斥锁
void show()
{lock.lock();try{code...}finally{lock.unlock();  //释放锁一定要做}
}

接口Condition :
它替代了Object中的wait notify notifyAll方法。
将这些监视器方法单独进行了封装,变成Condition监视器对象。可以任意锁进行组合。
await();
signal();
signalAll();

API:
Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

JDK1.5更新图解:

JDK1.5之前实现代码:

/*
生产者,消费者多生产者,多消费者
*/
class Resource
{private String name;private int count = 1;private boolean flag = false;public synchronized void set(String name){while(flag)         //if(flag)          //会发生死锁                                                 //解决方案:全部唤醒, notifyAll();try{wait();       //如果等待了,唤醒的时候从这里开始,不用进行前面的判断。所以有可能线程跳过了判断继续执行。//解决方案将if 改成while,但可能导致四个线程全部等待,发生死锁}catch (InterruptedException e){}this.name = name + count;System.out.println(Thread.currentThread().getName() + "生产了 " + this.name);count++;flag = true;notifyAll();}public synchronized void out(){while(!flag)        //if(!flag)        //解决方案改成while    try{wait();          //如果等待了,唤醒的时候从这里开始,不用进行前面的判断。}catch (InterruptedException e){}System.out.println(Thread.currentThread().getName() +"吃掉了 " + name);flag = false;notifyAll();}}class Producer implements Runnable
{Resource r;Producer(Resource r){this.r = r;}public void run(){while(true){r.set("烤鸭");}}
}class Consumer implements Runnable
{Resource r;Consumer(Resource r){this.r = r;}public void run(){while(true){r.out();}}
}class  ProducerConsumerDemo
{public static void main(String[] args) {Resource r = new Resource();Producer p = new Producer(r);Consumer c = new Consumer(r);Thread t1 = new Thread(p,"生产者1");Thread t2 = new Thread(p,"生产者2");Thread t3 = new Thread(c,"消费者1");Thread t4 = new Thread(c,"消费者2");t1.start();t2.start();t3.start();t4.start();}
}

JDK1.5之 后 实现代码:

/*
生产者,消费者多生产者,多消费者jdk1.5后的解决方案:*/
import java.util.concurrent.locks.*;   //导入lock包class Resource
{private String name;private int count = 1;private boolean flag = false;Lock lock =new  ReentrantLock();   //创建一个锁对象Condition producer_con = lock.newCondition();  //通过已有的锁,获得该锁上的监视器对象Condition consumer_con = lock.newCondition();public  void set(String name){lock.lock();    // 获取锁try{while(flag)         //if(flag)          //会发生死锁                                                 //解决方案:全部唤醒, notifyAll();try{producer_con.await();       //如果等待了,唤醒的时候从这里开始,不用进行前面的判断。所以有可能线程跳过了判断继续执行。//解决方案将if 改成while,但可能导致四个线程全部等待,发生死锁}catch (InterruptedException e){}this.name = name + count;System.out.println(Thread.currentThread().getName() + "生产了 " + this.name);count++;flag = true;consumer_con.signal();}finally{lock.unlock();  //释放锁}}public  void out(){lock.lock();    // 获取锁try{while(!flag)        //if(!flag)        //解决方案改成while    try{consumer_con.await();          //如果等待了,唤醒的时候从这里开始,不用进行前面的判断。}catch (InterruptedException e){}System.out.println(Thread.currentThread().getName() +"吃掉了 " + name);flag = false;producer_con.signal();}finally{lock.unlock();  //释放锁}}}class Producer implements Runnable
{Resource r;Producer(Resource r){this.r = r;}public void run(){while(true){r.set("烤鸭");}}
}class Consumer implements Runnable
{Resource r;Consumer(Resource r){this.r = r;}public void run(){while(true){r.out();}}
}class  ProducerConsumerDemo
{public static void main(String[] args) {Resource r = new Resource();Producer p = new Producer(r);Consumer c = new Consumer(r);Thread t1 = new Thread(p,"生产者1");Thread t2 = new Thread(p,"生产者2");Thread t3 = new Thread(c,"消费者1");Thread t4 = new Thread(c,"消费者2");t1.start();t2.start();t3.start();t4.start();}
}

API范例 补充:

 import java.util.concurrent.locks.*;class BoundedBuffer {final Lock lock = new ReentrantLock();final Condition notFull  = lock.newCondition(); final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100];int putptr, takeptr, count;public void put(Object x) throws InterruptedException {lock.lock();try {while (count == items.length) notFull.await();items[putptr] = x; System.out.println(Thread.currentThread().getName() + " produced " +   putptr);if (++putptr == items.length) putptr = 0;++count;notEmpty.signal();} finally {lock.unlock();}}public Object take() throws InterruptedException {lock.lock();try {while (count == 0) notEmpty.await();Object x = items[takeptr]; System.out.println(Thread.currentThread().getName() + " consum " + takeptr);if (++takeptr == items.length) takeptr = 0;--count;notFull.signal();return x;} finally {lock.unlock();}} }class Producer implements Runnable
{BoundedBuffer b;Producer(BoundedBuffer b){this.b = b;}public void run(){while(true){try{b.put(new Object());}catch (Exception e){}       }}
}class Consumer implements Runnable
{BoundedBuffer b;Consumer(BoundedBuffer b){this.b = b;}public void run(){while(true){   try{b.take();}catch (Exception e){}}}
}class ProducerConsumerAPIDemo
{public static void main(String[] args) {BoundedBuffer boun = new BoundedBuffer();Producer pro = new Producer(boun);Consumer cons = new Consumer(boun);Thread t1 = new Thread(pro,"Producer1");Thread t2 = new Thread(pro,"Producer2");Thread t3 = new Thread(cons,"Consumer1");Thread t4 = new Thread(cons,"Consumer2");t1.start();t2.start();t3.start();t4.start();}
}

谁拿锁谁执行。

5.wait 和 sleep的区别:

1.wait可以指定时间也可以不指定。sleep必须指定时间
2.在同步中时,对于CPU的执行权和锁的处理不同。
wait: 释放执行权,释放锁
sleep: 释放执行权,不释放锁

6.停止线程:

1.stop方法:过时
2.run方法结束:标记法任务中都会有循环结构,只要控制住循环就可以结束任务。控制循环通常就用定义标记来完成。
3.线程处于了冻结状态,无法读取标记。
public synchronized void run()
{while(flag){wait();...}
}
Thread方法:interrupt()中断线程。会抛出异常。可以使用interrupt()方法将线程从冻结状态强制恢复到运行状态中来,让线程具备cpu的执行资格。强制动作会发生冻结状态异常InterruptedException,记得要处理。然后给标记赋值,让其强制读取。结束线程。public synchronized void run()
{while(flag){try{wait();}catch(InterruptedException e){}flag =flase;}
}
t1.interrupt();   //强制唤醒

标记法示例:

class StopThread implements Runnable{private boolean flag = true;public void run(){while(flag){System.out.println(Thread.currentThread().getName()+".....");}}public void setFlag(){flag = false;}}class StopThreadDemo{public static void main(String[] args){StopThread st = new StopThread();Thread t1 = new Thread(st);Thread t2 = new Thread(st);t1.start();t2.start();int num = 1;for(;;){if(++num==50){st.setFlag();break;}System.out.println("main......"  + num);}System.out.println("over");}}

7.守护线程函数 setDaemon():将线程设置为后台线程(守护线程,用户线程等)。
前台线程必须手动结束。
当前台线程全部结束后,后台线程会自动结束。
t1.setDaemon(true);

当正在运行的线程都是守护线程时,Java 虚拟机退出。

8.其他方法:

1.join(): 等待该线程终止。 throws InterruptedException
先让该线程运行完到终止。也可以让冻结的线程强制恢复(interrupt()方法的功能)。
t1.join();//t1线程要申请加入进来,运行。这时主线程会将执行权释放出来,执行资格也释放,处于冻结状态。等t1结束后主线程再执行。临时加入一个线程运算时可以使用join方法。2.toString(): 返回该线程的字符串表示形式,包括线程名称、优先级和线程组。  例:Thread[Thread-0,5,main] 优先级: 获取cpu执行权的几率,范围1—10。其中关键的几个优先级进行了字段封装:静态常量
MAX_PRIORITY 线程可以具有的最高优先级。10
MIN_PRIORITY 线程可以具有的最低优先级。1
NORM_PRIORITY 分配给线程的默认优先级。5线程组:操作一个组的线程。方便。3.setPriority():更改线程的优先级。
例:  //t2.setPriority(10);
t2.setPriority(Thread.MAX_PRIORITY) //cpu会稍微优先照顾一下4.Thread.yield():线程临时暂停,释放执行权。给其他线程机会,自己同时也有机会。

9.快速创建线程:

//线程的子类对象,匿名内部类
class ThreadTest
{public static void main(String[] args){new Thread()        //线程一:直接创建Thread子类对象{public void run(){for(int x=0; x<50; x++){System.out.println(Thread.currentThread().getName()+ "......x= " + x);}}}.start();new Thread(new Runnable()   //线程二:创建Runnable接口的子类对象封装方法,把方法对象传给Theard线程对象       {public void run(){for(int x=0; x<50; x++){System.out.println(Thread.currentThread().getName()+ "...........y= " + x);}}}).start();for(int x=0; x<50; x++)   //线程三:主函数{System.out.println(Thread.currentThread().getName()+  "...z= " + x);}}
}

10.多线程面试题:

1.class Test implements Runnable
{public void run(Thread t)   //这是子类的特有方法,并没有实现接口Runnable
的run()方法,所以该类要么是抽象类,要么就要覆盖run方法。显然没有定义抽象类,所以会报错。{}
}2.class ThreadTest
{public static void main(String[] args){new Thread   //没有任务对象,以线程类本身为主(new Runnable()   //没有子类,以任务对象为主{public void run(){System.out.println("runnable run");}}){  //以子类为主public void run(){System.out.println("subThread run");}}.start();}
}

3.2多线程(线程通信)相关推荐

  1. java多线程通信_Java多线程-线程通信

    原标题:Java多线程-线程通信 通信的方式 要想实现多个线程之间的协同,如:线程执行先后顺序.获取某个线程执行的结果等等.涉及到线程之间的相互通信,分为下面四类: 文件共享 网络共享 共享变量 JD ...

  2. Java多线程---线程通信(wait,notifyAll,生产者消费者经典范式,owner wait set,自定义显式锁BooleanLock)

    转自:https://blog.csdn.net/qq_35995514/article/details/91128585 1 学习内容 notifyAll 生产者.消费者经典范式 线程休息室 wai ...

  3. 多线程-线程通信:生产者消费者例题

    /*** 线程通信的应用:经典例题:生产者/消费者问题** 生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处取走产品,* 店员一次只能持有固定数量的产品( ...

  4. java多线程 - 线程通信

    当线程在系统内运行时,程序通常无法准确控制线程的轮换执行,但是可以通过一些机制来保证线程协调运行. 由同步监视器对象协调线程 实现这种功能可以借助于Object类提供的wait().notify(). ...

  5. Java多线程-线程通信

    通信的方式 要想实现多个线程之间的协同,如:线程执行先后顺序.获取某个线程执行的结果等等.涉及到线程之间的相互通信,分为下面四类: 文件共享 网络共享 共享变量 JDK提供的线程协调API suspe ...

  6. C++多线程:Linux 线程通信,唤醒,互斥锁(未完待续)

    c++ multi thread message sending and notify 线程通信常用的方法有共享内存和消息传递,推荐使用消息传递. 最常用的就是管道了,可以使用匿名管道或者命名管道. ...

  7. 同软件多个线程设置不同ip_5-13网络编程(附带多线程死锁,线程通信)

    0513多线程 死锁 当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步.这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁 线程通信 生产者消费者模式 模拟街道案例 wai ...

  8. Java多线程之线程通信之生产者消费者阻塞队列版

    Java多线程之线程通信之生产者消费者传统版和阻塞队列版 目录 线程通信之生产者消费者传统版 线程通信之生产者消费者阻塞队列版 1. 线程通信之生产者消费者传统版 题目: 一个初始值为零的变量,两个线 ...

  9. java 管程通信_Java多线程07_线程通信之管程法与信号灯法

    Java多线程07_线程通信之管程法与信号灯法 线程通信 的应用场景是 消费者/生产者问题: 解决线程通信的方法: wait()表示线程一直等待,直到接到通知(会释放锁) wait(long time ...

  10. 多线程编程、线程同步|安全和线程通信

    多线程编程 多线程的优势 线程在程序中是独立的.并发的执行流,与分隔的进程相比,进程中的线程之间的隔离程度要小.他们共享内存.文件句柄和其他每个进程应有的状态. 因为线程的划分尺度小于进程,使得多线程 ...

最新文章

  1. Hibernate复习之Hibernate基本介绍
  2. Altium Designer 正反面布元器件
  3. [数分提高]2014-2015-2第4教学周第1次课
  4. 【FluidSynth】SoundFont 音源文件资料收集 ( SoundFont 规范 | SoundFont 音源下载 | SoundFont 编辑器 | 博客资源 )
  5. 【Android 性能优化】应用启动优化 ( 启动优化项目 | 界面启动时间 | 启动优化项目 | 方法追踪 MethodTracing )
  6. 日本社交餐厅评论服务平台Retty获1050万美元D轮融资
  7. MFC与OpenCv中的图片转换实例
  8. 牛客网在线编程:分苹果
  9. Ruby 101:重用、隐藏和多态
  10. 十多款优秀的Vue组件库介绍
  11. pytorch nn.MSELoss
  12. 数据库中间表插入乱序
  13. MATLAB实现连续周期信号的频谱分析(正余弦波信号举例)
  14. docker容器别人访问很卡_一篇文章带你走进Docker的世界
  15. 探测器类的电路设计流程框图
  16. 3097: Hash Killer I
  17. 汽车驾驶 - 如何调整汽车后视镜
  18. iOS数据持久化设计探讨(NSCache,PINCache,YYCache,CoreData,FMDB,WCDB,Realm)
  19. python高级--美国人口分析(Numpy,Pandas)
  20. 麦迪关键球失误的背后

热门文章

  1. c语言数组下标为负数
  2. 字符串去除空格和回车
  3. 广东计算机类专科院校排名,广东省高职院校全国排名+各院校王牌专业
  4. Delphi D10.1 移动开发中APP界面基本布局(一)
  5. 2022年中国科技与IT十大趋势
  6. MindManager揭秘:中国航母史
  7. 【软件安装】记录MySQL5.7.37安装过程以及出现的问题
  8. iOS图层配合核心动画详解
  9. 《超级快速阅读》读后感
  10. 2018-2019-2 20165315 《网络对抗技术》Exp3 免杀原理与实践