线程间通信
线程间通信–等待唤醒机制
/**
* 线程间通信:
* 多个线程在处理同一资源,但是任务却不同
*/
//等待唤醒机制
//设计的方法:
//1.wait();让线程处于冻结状态(线程释放cpu执行权,被wait的线程会存放在线程池中)
//2.notify();唤醒线程池中的一个线程(任意)
//3.notifyAll();唤醒线程池中所有线程
//这些方法必须定义在同步中,因为这些方法是用于操作线程的方法,必须要明确到底操作的是哪个锁上的线程
//为什么操作线程的方法wait(),notify,notifyAll定义在了Object类中,
//因为这些方法是监视器的方法。监视器其实就是锁。
//锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。
//资源
class Resource{
String name;
String sex;
Boolean flag = false;
}
//输入
class Input implements Runnable{
Resource r;
Input(Resource r){
this.r = r;
}
public void run(){
int x = 0;
while(true){
synchronized(r){
if(r.flag)
try {
r.wait();
} catch (Exception e) {
//TODO: handle exception
}
if(x==0){
this.r.name = "zxy";
this.r.sex = "man";
}
else{
this.r.name = "康萍萍";
this.r.sex = "女";
}
r.flag = true;
r.notify();
}
x = (x+1)%2;
}
}
}
//输出
class Output implements Runnable{
Resource r;
Output(Resource r){
this.r = r;
}
public void run(){
while(true){
synchronized(r){
if(!r.flag)
try {
r.wait();
} catch (Exception e) {
//TODO: handle exception
}
System.out.println(this.r.name+"..."+this.r.sex);
r.flag = false;
r.notify();
}
}
}
}
class MyLock{
public static Object locka = new Object();
public static Object lockb = new Object();
}
public class packDemo{
public static void main(String[] args){
Resource r = new Resource();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
//上面代码优化
//资源
class Resource{
private String name;
private String sex;
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;
this.flag = true;
this.notify();
}
public synchronized void show(){
if(!this.flag)
try {this.wait();} catch (Exception e) {}
System.out.println(name+"......"+sex);
this.flag = false;
this.notify();
}
}
//输入
class Input implements Runnable{
Resource r;
Input(Resource r){
this.r = r;
}
public void run(){
int x = 0;
while(true){
if(x==0){
r.set("zxy", "man");
}
else{
r.set("康萍萍", "女");
}
x = (x+1)%2;
}
}
}
//输出
class Output implements Runnable{
Resource r;
Output(Resource r){
this.r = r;
}
public void run(){
while(true){
r.show();
}
}
}
class MyLock{
public static Object locka = new Object();
public static Object lockb = new Object();
}
public class packDemo{
public static void main(String[] args){
Resource r = new Resource();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
线程间通信–多生产者多消费者问题
/**
* 生产者,消费者
* 多生产者,多消费者
* if判断标记,只有一次,会导致不该运行的线程运行了,出现数据错误的情况
* while判断标记,解决了线程获取执行权后,是否要运行
* notify:只能唤醒一个线程,如果本方唤醒了本方,没有意义。而且while判断标记加notify会导致死锁。
* notifyAll解决了本方线程一定会唤醒对方线程的问题。
*/
class Resources{
private String name;
private int count = 1;
private Boolean flag = false;
public synchronized void set(String name){
while(flag)//为了让多个生产者线程在wait醒来之后再次检测flag,将if改为while
try {this.wait();} catch (Exception e) {}
this.name = name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者..."+name);
flag = true;
notifyAll();
}
public synchronized void out(){
while(!flag)
try {this.wait();} catch (Exception e) {}
System.out.println(Thread.currentThread().getName()+"...消费者..."+name);
flag = false;
notifyAll();
}
}
class Producer implements Runnable{
private Resources r;
Producer(Resources r){
this.r = r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resources r;
Consumer(Resources r){
this.r = r;
}
public void run(){
while(true){
r.out();
}
}
}
public class packDemo{
public static void main(String[] args){
Resources r = new Resources();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
//Lock接口:出现替代了同步代码块和同步函数。将同步的隐式锁操作变成了显示锁操作,同时一个锁可以加多个监视器
//lock方法获取锁,unlock方法释放锁(通常需要定义在finally代码块中)
//Condition接口:出现替代了Object中的wait,notify,notifyAll方法。
// 将这些监视器方法单独进行了封装,变成Condition监视器对象。
// 可以与任意锁进行组合
// await();
// signal();
// signalAll();
JDK1.5替代之后,上面代码可更新为
import java.util.concurrent.locks.*;
class Resources{
private String name;
private int count = 1;
private Boolean flag = false;
Lock lock = new ReentrantLock();
//通过已有的锁获取该锁上的监视器对象
// Condition con = lock.newCondition();
//通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者
Condition producer_con = lock.newCondition();
Condition consumer_con = lock.newCondition();
public void set(String name){
lock.lock();
try{
while(flag)//为了让多个生产者线程在wait醒来之后再次检测flag,将if改为while
//try {this.wait();} catch (Exception e) {}
try {//con.await();
producer_con.await();
} catch (Exception e) {}
this.name = name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者..."+name);
flag = true;
//notifyAll();
// con.signalAll();
consumer_con.signal();
}
finally{
lock.unlock();
}
}
public void out(){
lock.lock();
try{
while(!flag)
//try {this.wait();} catch (Exception e) {}
try {//con.await();
consumer_con.await();
} catch (Exception e) {}
System.out.println(Thread.currentThread().getName()+"...消费者..."+name);
flag = false;
//notifyAll();
// con.signalAll();
producer_con.signal();
}
finally{
lock.unlock();
}
}
}
class Producer implements Runnable{
private Resources r;
Producer(Resources r){
this.r = r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resources r;
Consumer(Resources r){
this.r = r;
}
public void run(){
while(true){
r.out();
}
}
}
public class packDemo{
public static void main(String[] args){
Resources r = new Resources();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
线程间通信–wait和sleep的区别
// wait和sleep的区别?
// 1.wait可以指定时间也可以不指定。
// sleep必须指定时间
// 2.在同步中时,对cpu的执行权和锁的处理不同
// wait 释放执行权,释放锁
// sleep 释放执行权,不释放锁
线程间通信–停止线程方式interrupt
/*
停止线程:
1.stop方法
2.run方法结束
怎么控制线程的任务结束呢?
1.任务中都会有循环结构,只要控制住循环就可以结束任务。
控制循环通常就用定义标记来完成。
2.可以使用interrupt将线程从冻结强制恢复到运行状态中来,让线程具备cpu的执行资格
但是强制动作会发生中断异常,记得处理
setDaemon()
*/
class StopThread implements Runnable{
private Boolean flag = true;
public void run(){
while(flag){
try{
wait();
}
catch(InterruptedException e){
System.out.println(Thread.currentThread().getName()+"......"+e);
flag = false;
}
System.out.println(Thread.currentThread().getName()+"+++++");
}
}
public void setFlag(){
flag = false;
}
}
public class packDemo{
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 = 0;
while(true){
if(num++==50){
// st.setFlag();
t1.interrupt();//可以使用interrupt将线程从冻结强制恢复到运行状态中来
//让线程具备cpu的执行资格
t2.interrupt();
break;
}
System.out.println("main....."+num);
}
}
}
线程间通信–守护线程setDaemon
多线程其他方法
//thread.join()//等待该线程终止
//Thread.yield();//释放执行权,让其他线程有机会
//Thread.setPriority(Thread.MAX_PRIORITY);//改变优先级
class Demo implements Runnable{
public void run(){
for(int x=0;x<50;x++){
System.out.println(Thread.currentThread().getName()+"++++++"+x);
}
}
}
public class packDemo{
public static void main(String[] args) throws Exception{
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
//t1.join();//t1线程要申请加入进来,运行
t2.start();
t2.setPriority(Thread.MAX_PRIORITY);
for(int i=0;i<50;i++){
// System.out.println(Thread.currentThread().getName()+"...main..."+i);
}
// System.out.println("hello");
}
}