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. 面试大厂背怼!这都搞不定,你只能做“搬运工”!
  2. 小甲鱼python数字游戏给三次机会_【python 入门案例】小甲鱼python入门 猜数字游戏...
  3. 水题:P2799 国王的魔镜
  4. vuex登录后设置token
  5. 老师:你根本不知道我有多想逃课
  6. 架构设计(6)---Web架构师究竟都要学些什么?
  7. linphone相关(转)
  8. 金蝶记账王和易记账哪个好_代理记账比招聘全职会计好在哪-义乌丹诚代理记账...
  9. 查看生产DB2数据库空间及使用情况
  10. Python数据分析基础: 数据缺失值处理
  11. 地下城与勇士(DNF)安图恩副本(黑雾之源、震颤的大地、舰炮防御战、擎天之柱、能量阻截战、黑色火山、安徒恩的心脏)(童年的回忆)
  12. IOS UI学习 UI 十个小控件 初度学习
  13. python工商银行流水_python爬取银行名称和官网地址
  14. 淘宝和拼多多同类别测评
  15. Metasploitable2虚拟机镜像下载地址
  16. 如何制作并使用python发布的模块压缩包和whl包,并进行pip安装和使用教程,加上传Pypi,上传之后又如何增删whl项目
  17. Python通过MQTT协议上传物联网数据给ThingsBoard
  18. 激活函数,优化技术和损失函数
  19. 【英语阅读】纽约时报 | 乔布斯是对的:手机和iPad杀死了个人电脑
  20. SwiftUI 界面刷新 外部修改 ObservableObject @ObservedObject @Published

热门文章

  1. 【个人Onenote笔记】整理+搬运
  2. flac文件如何转mp3?
  3. 周末运动,山地骑行,关于山地车你不得不知道的基础知识
  4. Unity 3D游戏发布到Android平台
  5. SuperMap 三维GIS应用
  6. gif透明背景动画_【超实用干货! 】iPad上的动画App大推荐
  7. 主数据如何落地?建主数据系统统一管控还是各自管理?
  8. 问题 A: DS二叉树—二叉树构建与遍历
  9. linux配置repo文件夹,CentOS yum的配置文件 repo文件详解
  10. Android中级面筋:开发2年的程序员如何短期突击面试?跟着这几步去准备