Java多线程 二 线程间通信

Posted qiangge-python

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程 二 线程间通信相关的知识,希望对你有一定的参考价值。

线程间通信:

多个线程在处理同一资源,但是

 

等待唤醒机制

涉及的方法:

1、wait() 让线程处于冻结状态,被wait的线程会被存储到线程池中。 

2、notify() 唤醒线程池中的一个线程(任意)

3、notifyAll() 唤醒线程池中的所有线程、、

这些方法都必须定义在同步中,

因为这些方法是用于操作线程状态的方法。

必须明确到底操作的那个锁上的线程。

 

为什么操作线程的方法wait notify notifyAll定义在了Object中。

因为这些方法是监视器方法,监视器其实就是锁。

锁可以是任意的对象,任意的对象调用的方法一定定义在Object类中。

package com.pzq.thread;

public class SyncDemo3 

    public static void main(String[] args) 

        Resource resource = new Resource();
        Input input = new Input(resource);
        OutPut outPut = new OutPut(resource);
        Thread threadInput = new Thread(input);
        Thread threadOuput = new Thread(outPut);
        threadInput.start();
        threadOuput.start();
    



class Input implements Runnable 

    Resource r;

    public Input(Resource r) 
        this.r = r;
    

    @Override
    public void run() 
        int x = 0;
        while (true) 
            synchronized (r) 

                if (r.flag) 
                    try 
                        r.wait();
                     catch (InterruptedException e) 
                        e.printStackTrace();
                    
                
                if (x == 0) 
                    r.name = "mike";
                    r.sex = "nan";
                 else 
                    r.name = "丽丽";
                    r.sex = "女女女女女女女";
                
                r.flag = true;
                r.notify();
            
            x = (x + 1) % 2;
        
    



class OutPut implements Runnable 

    Resource r;

    public OutPut(Resource r) 
        this.r = r;
    

    @Override
    public void run() 
        while (true) 
            synchronized (r) 
                if (!r.flag) 
                    try 
                        r.wait();
                     catch (InterruptedException e) 
                        e.printStackTrace();
                    
                
                System.out.println(r.name + "......" + r.sex);
                r.flag = false;
                r.notify();
            
        
    



class Resource 
    String name;
    String sex;
    boolean flag = false;

    public Resource() 
    

    public Resource(String name, String sex) 
        this.name = name;
        this.sex = sex;
    

 

生产者消费者

代码优化,将同步方法封装到属性当中

package com.pzq.thread;

public class SyncDemo3 

    public static void main(String[] args) 

        Resource resource = new Resource();
        Input input = new Input(resource);
        OutPut outPut = new OutPut(resource);
        Thread threadInput = new Thread(input);
        Thread threadOuput = new Thread(outPut);
        threadInput.start();
        threadOuput.start();
    



class Input implements Runnable 

    Resource r;

    public Input(Resource r) 
        this.r = r;
    

    @Override
    public void run() 
        int x = 0;
        while (true) 
            if (x == 0) 
                r.set("mike", "nan");
             else 
                r.set("丽丽", "=========女");
            
            x = (x + 1) % 2;
        
    



class OutPut implements Runnable 

    Resource r;

    public OutPut(Resource r) 
        this.r = r;
    

    @Override
    public void run() 
        while (true) 
            r.out();
        
    



class Resource 
    private String name;
    private String sex;
    private boolean flag = false;

    public Resource() 
    

    public synchronized void set(String name, String sex) 
        if (flag) 
            try 
                this.wait();
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
        this.name = name;
        this.sex = sex;
        flag = true;
        this.notify();
    

    public synchronized void out() 
        if (!flag) 
            try 
                this.wait();
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
        System.out.println(this.name + "....." + this.sex);
        flag = false;
        this.notify();
    

单生产单消费

package com.pzq.thread;

public class SyncDemo4 

    public static void main(String[] args) 

        Resource2 resource = new Resource2();
        Producter input = new Producter(resource);
        Customer outPut = new Customer(resource);
        Thread threadInput = new Thread(input);
        Thread threadOuput = new Thread(outPut);
        threadInput.start();
        threadOuput.start();
    



class Producter implements Runnable 

    Resource2 r;

    public Producter(Resource2 r) 
        this.r = r;
    

    @Override
    public void run() 
        while (true) 
            r.set("烤鸭");
        
    



class Customer implements Runnable 

    Resource2 r;

    public Customer(Resource2 r) 
        this.r = r;
    

    @Override
    public void run() 
        while (true) 
            r.out();
        
    



class Resource2 
    private String name;
    private boolean flag = false;
    private int count = 1;

    public Resource2() 
    

    public synchronized void set(String name) 
        if (flag) 
            try 
                this.wait();
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
        this.name = name + count;
        count++;
        System.out.println(Thread.currentThread().getName() + "生产者+++" + this.name);
        flag = true;
        this.notify();
    

    public synchronized void out() 
        if (!flag) 
            try 
                this.wait();
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
        System.out.println(Thread.currentThread().getName() + "消费者" + "=================" + this.name);
        flag = false;
        this.notify();
    

 

多生产者多消费者

if判断标记,只有一次,会导致不该运行的线程运行了。出现了数据错误的情况。

while判断标记,解决了线程获取执行权后,是否要运行

notify只能唤醒一个线程,如果本方唤醒了本方,就没有意义了。而且 while判断标记+notify会导致死锁。

notifyAll解决了,本方线程一定会唤醒对方线程。

package com.pzq.thread;

public class SyncDemo4 

    public static void main(String[] args) 

        Resource2 resource = new Resource2();
        Producter input = new Producter(resource);
        Customer outPut = new Customer(resource);
        Thread threadInput1 = new Thread(input);
        Thread threadInput2 = new Thread(input);
        Thread threadInput3 = new Thread(input);
        Thread threadOuput1 = new Thread(outPut);
        Thread threadOuput2 = new Thread(outPut);
        Thread threadOuput3 = new Thread(outPut);
        Thread threadOuput4 = new Thread(outPut);
        Thread threadOuput5 = new Thread(outPut);
        threadInput1.start();
        threadInput2.start();
        threadInput3.start();
        threadOuput1.start();
        threadOuput2.start();
        threadOuput3.start();
        threadOuput4.start();
        threadOuput5.start();
    



class Producter implements Runnable 

    Resource2 r;

    public Producter(Resource2 r) 
        this.r = r;
    

    @Override
    public void run() 
        while (true) 
            r.set("烤鸭");
        
    



class Customer implements Runnable 

    Resource2 r;

    public Customer(Resource2 r) 
        this.r = r;
    

    @Override
    public void run() 
        while (true) 
            r.out();
        
    



class Resource2 
    private String name;
    private boolean flag = false;
    private int count = 1;

    public Resource2() 
    

    public synchronized void set(String name) 
        while (flag) 
            try 
                this.wait();
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
        this.name = name + count;
        count++;
        System.out.println(Thread.currentThread().getName() + "生产者+++" + this.name);
        flag = true;
        this.notifyAll();
    

    public synchronized void out() 
        while (!flag) 
            try 
                this.wait();
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
        System.out.println(Thread.currentThread().getName() + "消费者" + "=================" + this.name);
        flag = false;
        this.notifyAll();
    

 

多生产者多消费者 1.5新特性

jdk1.5以后将同步和锁封装成了对象。

并将操作锁的隐式方式定义到了该对象中,

将隐式动作变成了显示动作。

Lock接口:出现了替代同步代码块或者同步函数。将同步的隐式锁操作变成现实锁操作。

同时更为灵活,可以一个锁上加上多组监视器。

lock() 获取锁

unlock():释放锁,通常需要定义finally代码块中

 

Condition接口:出现替代了Object中的wait notify notifyAll方法。

  将这些监视器方法单独进行了封装,变成Condition监视器对象。

  可以任意锁进行组合。

 

await();

signal();

singnalAll

 

package com.pzq.thread;

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

public class SyncDemo4 

    public static void main(String[] args) 

        Resource2 resource = new Resource2();
        Producter input = new Producter(resource);
        Customer outPut = new Customer(resource);
        Thread threadInput1 = new Thread(input);
        Thread threadInput2 = new Thread(input);
        Thread threadInput3 = new Thread(input);
        Thread threadOuput1 = new Thread(outPut);
        Thread threadOuput2 = new Thread(outPut);
        Thread threadOuput3 = new Thread(outPut);
        Thread threadOuput4 = new Thread(outPut);
        Thread threadOuput5 = new Thread(outPut);
        threadInput1.start();
        threadInput2.start();
        threadInput3.start();
        threadOuput1.start();
        threadOuput2.start();
        threadOuput3.start();
        threadOuput4.start();
        threadOuput5.start();
    



class Producter implements Runnable 

    Resource2 r;

    public Producter(Resource2 r) 
        this.r = r;
    

    @Override
    public void run() 
        while (true) 
            r.set("烤鸭");
        
    



class Customer implements Runnable 

    Resource2 r;

    public Customer(Resource2 r) 
        this.r = r;
    

    @Override
    public void run() 
        while (true) 
            r.out();
        
    



class Resource2 
    private String name;
    private boolean flag = false;
    private int count = 1;

    // 创建一个锁对象
    Lock lock = new ReentrantLock();
    // 通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者
    Condition con_producter = lock.newCondition();
    Condition con_customer = lock.newCondition();

    public Resource2() 
    

    public void set(String name) 
        lock.lock();
        try 
            while (flag) 
                try 
                    con_producter.await();
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            
            this.name = name + count;
            count++;
            System.out.println(Thread.currentThread().getName() + "生产者+++" + this.name);
            flag = true;
            con_customer.signal();
         finally 
            lock.unlock();
        

    

    public void out() 
        lock.lock();
        try 
            while (!flag) 
                try 
                    con_customer.await();
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            
            System.out.println(Thread.currentThread().getName() + "消费者" + "=================" + this.name);
            flag = false;
            con_producter.signal();

         finally 
            lock.unlock();
        

    

 

定义一个容器的生产者消费者

package com.pzq.thread;

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

public class BoundBuffer 
    public static void main(String[] args) 

        Resources resources = new Resources();

        Products products = new Products(resources);
        Customers customers = new Customers(resources);

        new Thread(products).start();
        new Thread(products).start();
        new Thread(products).start();
        new Thread(customers).start();
        new Thread(customers).start();
        new Thread(customers).start();

    



class Customers implements Runnable 
    Resources rs;

    public Customers(Resources rs) 
        this.rs = rs;
    

    @Override
    public void run() 
        while (true) 
            try 
                rs.take();
                Thread.sleep(1000);
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
    



class Products implements Runnable 
    Resources rs;

    int count = 1;

    public Products(Resources rs) 
        this.rs = rs;
    

    @Override
    public void run() 
        while (true) 
            try 
                rs.put("烤鸭");
                Thread.sleep(1000);
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
    



class Resources 
    Lock lock = new ReentrantLock();
    Condition notEmpty = lock.newCondition();
    Condition notFull = lock.newCondition();
    Object[] buffer = new Object[100];
    int putptr, takeptr, count;

    public void put(Object x) throws InterruptedException 
        lock.lock();
        try 
            while (count == buffer.length) 
                notFull.await();
            
            buffer[putptr] = x;
            if (++putptr == buffer.length) 
                putptr = 0;
            
            ++count;
            System.out.println("-------" + Thread.currentThread().getName() + "生产了---" + (x.toString() + putptr));
            notEmpty.signal();

         finally 
            lock.unlock();
        
    

    public void take() throws InterruptedException 
        lock.lock();
        // Object x = null;
        try 
            while (count == 0) 
                notEmpty.await();
            
            Object x = buffer[takeptr];
            if (++takeptr == buffer.length) 
                takeptr = 0;
            
            --count;
            System.out.println("#######" + Thread.currentThread().getName() + "消费了####" + (x.toString() + takeptr));

            notFull.signal();

         finally 
            lock.unlock();
        
        // return x;
    

 

以上是关于Java多线程 二 线程间通信的主要内容,如果未能解决你的问题,请参考以下文章

多线程-线程间的通信

多线程-线程间的通信

Java基础教程:多线程基础——线程间的通信

Java 多线程线程间的通信

JAVA多线程之线程间的通信方式

Java多线程:线程间通信方式