栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java多线程学习笔记(3)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java多线程学习笔记(3)

java多线程学习笔记(3) 线程通信、管程 9、线程通信

Object的同步方法

	@IntrinsicCandidate
    public final native void notify();

    @IntrinsicCandidate
    public final native void notifyAll();

	public final void wait() throws InterruptedException {
        wait(0L);
    }

public final native void wait(long timeoutMillis) throws InterruptedException;

需要注意:wait(),notify(),notifyAll()这些方法必须使用在同步代码块或者同步方法中。如果在非同步控制方法或控制块里调用,程序能通过编译,但运行的时候,将得到 IllegalMonitorStateException 异常。

同步实例(两人交替买票)

class Ticket implements Runnable{
    //当前拥有的票数
    private  int i = 100;
    private Object ticketLock= new Object();
    @Override
    public void run() {
        while(true){
            synchronized (ticketLock){
                ticketLock.notify();
                if(i>0){
                    System.out.println(Thread.currentThread().getName()+".....sale...."+i--);
                }else break;
                try {
                    ticketLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
public static void main(String[] args) {
    Ticket t =new Ticket();
    new Thread(t).start();
    new Thread(t).start();
}

等效于使用lock和condition的代码如下

class Ticket implements Runnable{
    //当前拥有的票数
    private  int i = 100;
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    @Override
    public void run(){
        while(true){
            lock.lock();
            try {
                condition.signal();
                if(i>0){
                    System.out.println(Thread.currentThread().getName()+".....sale...."+i--);
                }else break;
                condition.await();
            }catch (InterruptedException e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }

        }
    }
}
10、管程和信号量 1、信号量
  1. P() 操作:将 count - 1,若 count < 0 时,线程进入等待队列
  2. V() 操作:将 count + 1,若 count <= 0 时,唤醒一个等待队列中的线程

用信号量实现阻塞队列

用一个二进制信号量mutex实现互斥访问;用两个资源信号量notFul,notEmptyl实现条件同步

public class BlockingQueueUseSemaphore {
    private final Object[] items;
    private Semaphore notFull;
    private Semaphore notEmpty;
    private Semaphore mutex;
    private int putIndex;
    private int takeIndex;

    public BlockingQueueUseSemaphore(int capacity) {
        this.items = new Object[capacity];
        notFull = new Semaphore(capacity);
        notEmpty = new Semaphore(0);
        mutex = new Semaphore(1);
    }

    public void enq(T x) throws InterruptedException {
        notFull.acquire();
        mutex.acquire();
        items[putIndex] = x;
        if (++putIndex == items.length) {
            putIndex = 0;
        }
        mutex.release();
        notEmpty.release();
    }

    public T deq() throws InterruptedException {
        notEmpty.acquire();
        mutex.acquire();
        T x = (T) items[takeIndex];
        if (++takeIndex == items.length) {
            takeIndex = 0;
        }
        mutex.release();
        notFull.release();
        return x;
    }
}
2、管程法

在信号量中,当 P 操作无法获取到锁时,将当前线程添加到同步队列(syncQueue)中。当其余线程 V 释放锁时,从同步队列中唤醒等待线程。但当有多个线程通过信号量 PV 配对时会异常复杂,所以管程中引入了等待队列(waitQueue)的概念,进一步封装这些复杂的操作.

管程中条件变量(condition variable)的概念,每一个条件变量对应一个等待队列

synchronized就是基于管程实现的,只包含一个同步队列,一个等待队列
AQS也是基于管程实现的,只包含一个同步队列,但是可以包含多个等待队列

用管程实现阻塞队列

public class BlockingQueueUseMonitor {
    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(E x) throws InterruptedException {
      lock.lock();
      try {
        while (count == items.length)
          notFull.await();
        items[putptr] = x;
        if (++putptr == items.length) putptr = 0;
        ++count;
        notEmpty.signal();
      } finally {
        lock.unlock();
      }
    }
    public E take() throws InterruptedException {
      lock.lock();
      try {
        while (count == 0)
          notEmpty.await();
        E x = (E) items[takeptr];
        if (++takeptr == items.length) takeptr = 0;
        --count;
        notFull.signal();
        return x;
      } finally {
        lock.unlock();
      }
    }
}

也可以使用基于管程实现的synchronized,以生产者消费者问题为例

class produce extends Thread{
    sycnContainer container;
    public produce(sycnContainer container) {
        this.container = container;
    }
    @Override
    public void run() {
        for(int i=1;i<100;i++){
            container.push(new product(i));
            System.out.println("生产第"+i+"个产品");
        }
    }
}
class  consume extends Thread{
    sycnContainer container;
    public consume(sycnContainer container) {
        this.container = container;
    }
    @Override
    public void run() {
        for(int i=1;i<100;i++){
            container.pop();
            System.out.println("消费第"+i+"个产品");
        }
    }
}
class product{
    int id;
    public product(int id) {
        this.id = id;
    }
}
class sycnContainer{
    private product[] ps = new product[10];
    private int count =0;
    public synchronized void push(product p){
        while(count==ps.length){
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        ps[count++] =p;
        this.notifyAll();
    }
    public synchronized  product pop(){
        while(count==0){
            try{
                this.wait();
            } catch (InterruptedException e){
                throw new RuntimeException();
            }
        }
        count--;
        this.notifyAll();
        return ps[count];
    }
}
public static void main(String[] args) {
    sycnContainer container =new sycnContainer();
    new produce(container).start();
    new consume(container).start();
}
11、wait、sleep、await 1、wait VS sleep

*相同点:*

  1. 都可以让线程休眠;
  2. 都可以响应 interrupt 的响应。

*不同点:*

  1. wait 必须在 synchronized 中使⽤,而 sleep 却不⽤;
  2. sleep 是 Thread 的⽅法,而 wait 是 Object 的⽅法;
  3. sleep 不释放锁,wait 释放锁;
  4. sleep 一定有明确的终止等待时间,而 wait 有可能无限期的等待下去;
  5. sleep 和 wait 产生的线程状态是不同的,sleep 是 TIMED_WAITING 状态,而 wait 是 WAITING 状态。
2、Condition VS Object的同步方法

*不同点:*

  1. lock不再用synchronize把同步代码包装起,但是需要Condition对应的lock上锁;
  2. 一个是基于对象监听器的同步方式,一个是基于 AQS同步机制的同步方式
  3. 使用lock和condition更灵活。在实际应用时可能需要多个等待队列,比如读和写。为了这个灵活性,lock将同步互斥控制和等待队列分离开来,互斥保证在某个时刻只有一个线程访问临界区(lock自己完成),等待队列负责保存被阻塞的线程(condition完成)。
暑期编程PK赛 得CSDN机械键盘等精美礼品!
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1016777.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号