两篇文章了解进程与线程( 进阶篇)

本文详细介绍了Java线程的高级概念,包括守护线程(Daemonic)的设置与作用,如在用户退出时确保资源清理;线程同步的原理与方法,如使用`synchronized`关键字和Lock锁防止数据不一致;线程死锁的预防准则,以及生产者-消费者模型中的协作机制;此外,还讨论了线程生命周期和线程池的使用,如不同类型的线程池实现(如`newFixedThreadPool`)及其在性能优化中的角色。
摘要由CSDN通过智能技术生成

一、守护线程与yield

1. 守护线程(Daemon):

   public final void setDaemon(boolean on) {
        checkAccess();
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        daemon = on;
    }
 public final boolean isDaemon() {
        return daemon;
    }

setDaemon()方法是将线程标记为daemon线程或用户线程。当运行的唯一线程都是守护线程时,JVM将退出。

isDaemon()方法是测试当前线程是否是守护线程。

public class ThreadDemo {
    public static void main(String[] args) {

        Thread thread = new Thread(new MyRunnableThread());

        thread.setDaemon(true);// 把线程设置为守护线程。当进程中没有用户线程是,JVM将退出,设置需要在启动之前设置
        thread.start();
        for (int i = 0; i < 50 ; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("主线程(用户线程)当前执行:"+i);

        }

    }
}
class MyRunnableThread implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 50 ; i++) {

            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("MyRunnableThread当前执行:"+i);
        }
    }
}

案例通过守护线程和用户线程(mainThread)做比较,注意,使用守护线程时要在start()之前,等待CPU调度之前设置为守护线程。 否则处于Alive()状态,会抛出异常。异常解释看上篇文章:两篇文章了解进程与线程( 基础篇)

可以看出,当主线程结束时,JVM退出,守护线程也就结束了。那么这个有什么用呢?举个例子,当我们的项目涉及用户下载时,当用户退出应用,主线程结束,如果非守护线程,下载继续执行,所以可以将下载功能依托于守护线程,当用户退出时退出,在Android开发中较常用。 但不要涉及到数据存储,否则用户线程结束时候,数据可能没来得及保存好。

2. yield:

   public static native void yield();

调用本地方法(C/C++写的功能),让一次。

准确来说,我觉得这个方法没啥用。。。

public class ThreadDemo {
    public static void main(String[] args) {

        Thread thread = new Thread(new MyRunnableThread());

        thread.start();
        for (int i = 0; i < 50 ; i++) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("主线程(用户线程)当前执行:"+i);

        }

    }
}
class MyRunnableThread implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 50 ; i++) {

            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (i == 6) Thread.yield();
            System.out.println("MyRunnableThread当前执行:"+i);
        }
    }
}

就让一次,抢CPU时间片时,当i == 6时候,让一次调度,并执行其他线程。

二、线程同步:

 1. 多线程共享数据:

在多线程的操作中,多个线程可能处理同一个数据资源,这就是多线程中的共享数据。

以售票为模拟,假设有十张票,两个窗口售卖。常规开两个线程同时处理会出现数据为假的问题,比如线程1已经卖了就剩3张了,可能线程2还有4张。

错误示例:

public class ThreadDemo {
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值