Java高级Day30-线程补充

线程插队
  1. yield:线程的礼让。让出cpu,让其他线程执行,但礼让的时间不确定,所以也不一定礼让成功

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

练习

//主线程每隔1s,输出hi,一共10次,当输出到第5次,启动一个子线程,每隔1s输出hello,等该线程输出10次hello后,退出,主线程继续输出hi,直到主线程退出
public class HelloJava {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new T1());
        for (int i = 0; i <= 10; i++) {
            System.out.println("hi" + i);
            if (i == 5){
                t1.start();
                t1.join();//立即将t3插入到main
            }
            Thread.sleep(1000);
        }
​
    }
}
class T1 implements Runnable{
    private int count = 0;
​
    @Override
    public void run() {
        while (true){
            System.out.println("hello" + (++count));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (count == 10){
                break;
            }
        }
    }
}
用户线程和守护线程
  1. 用户线程:也叫工作线程,当线程的任务执行完毕或通知方式结束

  2. 守护线程:一般是为工作现场服务的,当所有的用户线程结束,守护线程自动结束

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

//设置守护线程
myDaemonThread.setDaemon(true);
线程7大状态
  1. NEW //尚未启动的线程处于此状态

  2. RUNNABLE //在Java虚拟机中执行的线程处于此状态

  3. BLOCKED //被阻塞等待监视器锁定的线程处于此状态

  4. WATTING //正在等待另一个线程执行特定动作的线程处于此状态

  5. TIMED_WATTING //正在等待另一个线程执行动作到达指定等待时间的线程处于此状态

  6. TERMINATED //已退出的线程处于此状态

  7. READY //在RUNNABLE细分后,可以分成READY 和 RUNNING状态

线程同步机制
  1. 在多线程编程里,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问计数,确保数据在任何时刻,最多有一个线程访问,以确保数据的完整性

  2. 也可以这样理解:线程同步,即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作

线程同步方法:

  1. 同步代码块

    synchronized(对象){//得到对象的锁,才能操作同步代码
       //需要被同步代码
    }
  2. synchronized还可以放在方法声明中,表示整个方法为同步方法

    public synchronized void m(String name){
       //需要被同步的代码
    }

互斥锁:

  1. 互斥锁是为了保证共享数据操作的完整性

  2. 每个对象都对应一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能由一个线程访问该对象

  3. 关键字synchronized来与对象的互斥锁练习,当某个对象用synchronized修饰时,表面该对象在任一时刻只能由一个线程访问

  4. 同步的局限性:导致程序的执行效率变低

  5. 同步方法(非静态)的锁可以是this(当前对象),也可以是其他对象

  6. 同步方法(静态)的锁为当前类本身,即 类名.class

注意细节:

  1. 同步方法如果没有使用static修饰:默认锁对象为this

  2. 如果方法有static修饰,默认锁对象:当前类.class

  3. 实现的落地步骤:

·需要线分析上锁的代码

·选择同步代码块或同步方法

·要求多个线程的锁对象为同一个即可

线程死锁:

多个线程都占用了对方的资源,但不肯让,导致了死锁,在编程里是一定要避免死锁的发生

释放锁:

*下面的操作会释放锁

  1. 当前线程的同步方法,同步代码块执行结束

    案例:上厕所,完事出来

  2. 当前线程在同步代码块,同步方法中遇到break,return

    案例:没有正常的完事,经理叫他修改Bug,不得已出来

  3. 当前线程在同步代码块,同步方法中出现了未处理的Error或Exception,导致异常结束

    没有正常的完事,发现忘带纸,不得已出来

  4. 当前线程在同步代码块,同步方法中执行了线程对象的wait()方法,当前线程暂停,并释放锁

    没有正常完事,觉得需要酝酿下,所以出来等会再进去

不释放锁的情况:

  1. 线程执行同步代码块或同步方法时,程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行,不会释放锁

    案例:上厕所,太困了,在坑位上眯了一会

  2. 线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁

    提示:应尽量避免使用suspend()和resume()来控制线程,方法不在推荐使用

84.线程练习题

//1.在main方法中启动两个线程
//2.第1个线程循环随机打印100以内的整数
//3.直到第2个线程从键盘读取了“Q”命令
public class HelloJava {
    public static void main(String[] args) throws InterruptedException {
        A a = new A();
        a.start();
        B b = new B(a);
        b.start();
    }
}
class A extends Thread{
    private boolean loop = true;
    @Override
    public void run() {
        while (loop){
            System.out.println((int)(Math.random() * 100 + 1));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
    public void setLoop(boolean loop){
        this.loop = loop;
    }
}
class B extends Thread{
    private A a;
    private Scanner scanner = new Scanner(System.in);
​
    public B(A a){//构造器中,直接传入A类对象
        this.a = a;
    }
    @Override
    public void run(){
        //接收到用户的输入
        System.out.println("请输入你的指令(Q)表示退出");
        char key = scanner.next().toUpperCase().charAt(0);
        if (key == 'Q'){
            //以通知的方式结束A进程
            a.setLoop(false);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值