JAVA 多线程(三)

152 阅读2分钟

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

线程插队

  • join:线程的插队。插队的线程一旦插队成功,则肯定先执行完插入的线程的所有任务。

守护线程

  • 用户线程:也叫工作线程,当线程任务执行完结束或用上述通知的方式结束线程。
  • 守护线程:一般是为工作线程服务的,当所有用户的线程结束,守护线程自动结束

常见的守护线程:垃圾回收机制

//守护线程
public class Demo02RunnableDeamon {
    public static void main(String[] args) throws InterruptedException {
        T4 t4 = new T4();
        // 将t4线程设为守护线程 (当主线程执行完时,子线程随之停止)
        t4.setDaemon(true);
        t4.start();
        
        for (int i = 0; i < 10; i++) {
            System.out.println("主线程任务执行。。。");
            Thread.sleep(1000);
        }
    }
}

class T4 extends Thread {
    @Override
    public void run() {
        int count = 0;
        for (int i = 0; i < 20; i++) {
            System.out.println("子线程" + count);
            count++;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程安全问题

当多线程访问了共享数据后,就会出现线程安全的问题。比如:多个窗口同时卖1-100号票。

线程安全问题是不能产生的,我们可以让一个线程在访问共享数据的时候,无论是否失去CPU的执行权,让其他的线程只能等待当前线程买完票,其他线程再进行卖票。

保证使用一个线程在卖票即可!

线程同步

多线程并发访问一个资源的安全性问题: 也就是解决重复票与不存在票问题,Java中提供了同步机制 ( synchronized ) 来解决。

完成同步的三种方式:

  • 同步代码块
  • 同步方法
  • 锁机制

方式一:同步代码块

class TicketImpl implements Runnable {
    private int ticket = 100;
    // 1. 创建一个锁对象
    Object lock = new Object();
    
    
    @Override
    public void run() {
        while (true) {
            // 2. 将涉及到共享资源的写操作(ticket)的代码放到同步代码块中
            synchronized (lock) {
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + "- 第" + ticket + "张");
                    
                    try {
                        Thread.sleep(100);// 提高线程安全问题出现的频率,设置睡眠
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticket--;
                }
            }
        }
    }
}