JAVA 多线程(四)

105 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

方式二:同步方法

class TicketImpl implements Runnable {
    private int ticket = 100;
    
    @Override
    public void run() {
        while (true) {
            payTicket();
        }
    }
    
    public synchronized void payTicket() {
        if (ticket > 0) {
            System.out.println(Thread.currentThread().getName() + "- 第" + ticket + "张");
            try {
                Thread.sleep(100);// 提高线程安全问题出现的频率,设置睡眠
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ticket--;
        }
    }
}

# 注意:同步方法的锁对象是实现类的对象(this)

# 第二种方法:将同步锁改用this
public void payTicket() {
    synchronized (this) {
        if (ticket > 0) {
            System.out.println(Thread.currentThread().getName() + "- 第" + ticket + "张");
            try {
                Thread.sleep(100);// 提高线程安全问题出现的频率,设置睡眠
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ticket--;
        }
    }
}

方式三:锁机制

public class Demo04lock {
    public static void main(String[] args) {
        Ticketimpl runnable = new Ticketimpl();
        Thread thread1 = new Thread(runnable, "窗口1");
        Thread thread2 = new Thread(runnable, "窗口2");
        Thread thread3 = new Thread(runnable, "窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

class Ticketimpl implements Runnable {
    private static int ticket = 100;
    // 1. 在成员位置创建ReentrantLock对象
    Lock lock = new ReentrantLock();
    
    @Override
    public void run() {
        while (true) {
            payTicket();
        }
    }
    
    void payTicket() {
        // 2. 在可能会出现线程安全的代码前调用Lock接口中的方法lock获取锁
        lock.lock();
        if (ticket > 0) {
            try {
                System.out.println(Thread.currentThread().getName() + "- 第" + ticket + "张");
                Thread.sleep(100);
                ticket--;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 3. 在可能会出现线程安全的代码后调用Lock接口中的方法unlock释放锁
                lock.unlock();
            }
        }
    }
}

线程间的通信 ( 生产者与消费者问题 )

多个线程并发执行时, 在默认情况下CPU是随机切换线程的,当我们需要多个线程来共同完成一件任务,并且我们希望他们有规律的执行, 那么多线程之间需要一些协调通信,以此来帮我们达到多线程共同操作一份数据。

wait/notify 就是线程间的一种协作机制。

线程池

如果并发的线程数量很多,且每个线程都执行一个时间很短的任务就结束了,这样频繁创建、销毁线程就会大大降低 系统的效率。

好处

  1. 降低资源消耗。
  2. 提高响应速度。
  3. 提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线线程的数目。

创建线程池的方法:

  • 固定大小的线程池:newFixedThreadPool
  • 单线程池:singleThreadExecutor
  • 缓存线程池:CachedThreadPool
  • 定长周期性调度的线程池:schedulThreadPool