多线程基础-02

1. 守护线程

1.1 守护线程是什么

守护线程 (Daemon) 是在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件

1.2 守护线程的作用

守护线程并发编程中扮演着重要的角色,它们的主要作用是为其他前台线程的运行提供便利服务。这些服务可能包括但不限于垃圾回收 后台任务执行等。守护线程的特点是:它们是在后台运行的,并且仅在普通 非守护线程仍然运行时才需要。

守护线程在主执行完毕的时候,守护线程自动结束,如果主线程不结束,那么守护线程将会一直运行

1.3 守护线程的实现

例:

public class Shohu extends Thread{
    public void run(){
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("守护线程");
    }
}
public class MyTest {
    public static void main(String[] args) {
        Shohu shohu = new Shohu();//现成的实例
        shohu.setDaemon(true);//设置成为守护线程
        //守护的线程是    main(主线程)
        shohu.start();
        try {
            Thread.sleep(5000);//在这五秒之内   守护线程  需要工作
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("--------");// 主线程结束
    }
}

因为主线程里面的内容简单 怕看不出来效果 因此鼠鼠在主线程中添加了一个 sleep() 方法

运行以上代码后的结果:

运行中出现 守护线程 后会有五秒的停顿 

2. Wait()方法

2.1 Wait() 方法

Wait() 方法是 Object 类的方法,使用时必须存放在同步代码块(synchronized)中,他的作用是使当前执行 Wait() 方法的线程等待,在 Wait() 所在的代码行处暂停执行,并释放锁,直到接到通知或中断。在调用 Wait() 方法时可在括号中直接写入等待时间。如: wait(1000) 等待一秒

例:

public class WaitTest {

    private static Object object = new Object();

    static class Wait extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println("当前线程开始等待:" + this.getName());
                //
                try {
                    object.wait(10000);// 10s
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(this.getName() + "等待结束");
            }
        }
    }
}
public class MyTest2 {
    public static void main(String[] args) {
        WaitTest.Wait wait = new WaitTest.Wait();
        wait.setName("wait1");

        WaitTest.Wait wait2 = new WaitTest.Wait();
        wait2.setName("wait2");

        wait.start();
        wait2.start();
    }
}

 运行以上代码后的结果:

2.2 Notify() 方法

Notify() 方法是用来通知那些可能等待该锁的其他线程,如果有多个线程等待,那么唤醒的线程是随机的。

例:

public class WaitTest {

    private static Object object = new Object();

    static class Wait extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println("当前线程开始等待:" + this.getName());
                //
                try {
                    object.wait(10000);// 10s
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(this.getName() + "等待结束");
            }
        }
    }


    static class Notify extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println("开始唤醒线程:" + this.getName());
                object.notifyAll();
                System.out.println("唤醒线程:" + this.getName() + "等待结束");
            }
        }
    }
}
public class MyTest2 {
    public static void main(String[] args) {
        WaitTest.Wait wait = new WaitTest.Wait();
        wait.setName("wait1");

        WaitTest.Wait wait2 = new WaitTest.Wait();
        wait2.setName("wait2");

        wait.start();
        wait2.start();

        //唤醒线程
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        WaitTest.Notify notify = new WaitTest.Notify();
        notify.start();
    }
}

  运行以上代码后的结果:

2.3 NotifyAll() 方法

NotifyAll() 方法是用来唤醒所有的线程

总结:

1. Wait() 方法可以使线程暂停运行,而 Notify() 方法通知暂停的线程继续运行。

2. Wait() 方法会释放锁,Notify() 方法不会释放锁

3. Wait() 释放锁之后会回来继续执行时,必须先拿到锁,否则不会执行

3. Wait() 方法和 Sleep() 方法

相同点:

        1. 都是可以让线程进入休眠

        2. 都可以响应 Interrupt (中断) 请求

不相同点:

        1. wait 必须配合 synchronized  一起使用,而 sleep 不需要。

        2. wait 属于 Object(对象)的方法,而 sleep 属于 Thread(线程)的方法。

        3. wait 释放锁,而 sleep 不释放锁。

        4. wait 不需要传参,而 sleep 必须要传递一个数值类型参数。

        5. 一般情况下,sleep 只能等待超过时间之后再回复执行,而 wait 可以接收 notify/notifyAll之后就执行。

4. Lock

Lock 是一个类似于 synchronized  的线程同步机制。但是 Lock 比 synchronized  更加灵活。Lock 是个接口,有个实现类是 ReentrantLock 

Lock 必须要用户手动释放锁,如果没有主动释放锁,就有可能导致会出现锁死现象。

例:

public class MyRhradLock implements Runnable {
    private int tickect = 10;

    @Override
    public void run() {//代码块{}
        Lock lock = new ReentrantLock();
        try {
            while (tickect > 0) {
                lock.lock();//枷锁
                System.out.println(Thread.currentThread().getName() + "卖出去了一张,还剩" + tickect--);
            }
        } catch (Exception e) {

        } finally {
            lock.unlock();
        }
    }
}
public class MyTest2 {
    public static void main(String[] args) {
        MyRhradLock myRhradLock = new MyRhradLock();
        Thread thread = new Thread(myRhradLock,"张三");
        Thread thread1 = new Thread(myRhradLock,"张三四");
        Thread thread2 = new Thread(myRhradLock,"张三四五");

        thread.start();
        thread2.start();
        thread1.start();
    }
}

  运行以上代码后的结果:

5.  Volatile 关键字

Volatile 关键字的作用主要有两个:

        1. 线程的可见性: 当一个线程修改一个共享变量是,另一个线程能读取到这个修改的值.

        2. 顺序一致性: 禁止指令重排序。

例:

public class Num {
    private volatile int x;
    private volatile int y;

    //指令重播 x y x==y
    public void add(){
        System.out.println("开始调用");
        x++;
        y++;
        eq();
        System.out.println("调用结束");
    }

    public void eq(){
        System.out.println("x:"+x+"\ty:"+y+"\tx==y:"+(x==y));
    }

    public static void main(String[] args) {
        Num num = new Num();
        num.add();
    }
}

  运行以上代码后的结果:

 

 到此  多线程基础-02 结束

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值