Thread 类及常见方法

本文探讨了Java中Thread类的中断机制,包括join方法如何使主线程等待子线程完成,yield方法如何让当前线程放弃CPU执行权,以及如何通过中断标志来控制线程的执行。通过示例展示了线程状态的变化和中断操作的效果。
package package1128_2;

public class MyThread {
    public static void main(String[] args) {
        //直接写代码块里面
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("明天要剁手了");
            }
        }).start();
        System.out.println("今天还是要上课");
    }
}

按照以前的逻辑,先打印明天,再打印今天,但是结果却是

今天还是要上课
明天要剁手了

这是因为main线程和子线程执行代码,是由cpu执行调度的,它们是平级关系
创建并线程,会在操作系统里面真实的创建并让申请系统调度该线程,在申请后由cpu时间片调度执行(就绪态到运行态的过程).其中创建线程的动作是比较耗时的,所以先打印下面代码


阻塞方法


    public static void main(String[] args) throws InterruptedException {
        //直接写代码块里面
        Thread thread =  new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("明天要剁手");
            }
        });
        thread.start();
        thread.join();
        System.out.println("今天还是要上课");
    }

结果

明天要剁手
今天还是要上课

不调用join时,创建线程会耗时较长,main方法先打印"今天"
调用了join,表示thred(线程的引用)会加入到当前线程(JavaMain主线程),等待thread引用线程完毕才会执行打印"今天"的操作


创建10个线程,每个线程获取list的10000个元素
方法一:线程让步
yield(),由运行态转变为就绪态

yield()
A hint to the scheduler that the current thread is willing to yield its current use of a processor.

翻译:向调度示意当前这个线程愿意放弃对当前处理器的使用.

package package1128_2;

import java.util.*;

public class ThreadAdvantage {
    //多线程执行效率问题,集合
    public static List<String> randomList(){
        char[] chars = {'a','b','c','z','A'};//随机数
        List<String> list = new LinkedList<>();
        for (int i = 0; i < 100000; i++) {
            //取三个随机数
            int random = new Random().nextInt(chars.length);//取到长度范围内的一个数值
            char c = chars[random];
            list.add(String.valueOf(c));
        }
        return list;
    }
    public static void main(String[] args) {
        //初始化一个链表,启动很多线程
        List<String> list = randomList();
        //时间Date、 LocalDatetime
        long start = System.currentTimeMillis();
        //创建10个线程,每个线程获取list中的10000个元素
        for (int i = 0; i < 10; i++) {
            final int k = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 10000; j++) {
                        list.get(k*10000 + j);
                    }
                }
            }).start();
        }
        //第一种做法,线程让步
        while (Thread.activeCount() > 1){
            //表示超过一个线程在活跃的状态,
            //运行态线程遇到yield(),由运行态变到就绪态
            Thread.yield();
        }
 
        long end = System.currentTimeMillis();
        System.out.println((end - start));
    }
}

你试过,打印出的是非常跳跃的结果,只要当前线程活跃的个数大于一,在执行到end之前,我们让他放弃对cpu的执行,屈服下去,他就会进入就绪态,这时候cpu就会调度别的线程,依旧是运行到这里放弃,直到线程都跑完了,就计算end


方法二:阻塞方法
join:表示阻塞当前线程,而等待引用线程执行完毕

join()
Waits for this thread to die.

翻译:等待该线程执行完

public static void main(String[] args) {
        //初始化一个链表,启动很多线程
        List<String> list = randomList();
        //时间Date、 LocalDatetime
        long start = System.currentTimeMillis();
        //创建10个线程,每个线程获取list中的10000个元素
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            final int k = i;
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 10000; j++) {
                        list.get(k*10000 + j);
                    }
                }
            });
            threads[i].start();
        }
        for (Thread thread : threads){
            try {
            	//当前线程一直等待,被调用线程执行完毕.
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println((end - start));
    }

线程状态图在这里插入图片描述


中断

1.标志位方法

package package1129;

public class StopThread {
    private static volatile boolean myInterrupted = true;//标志位
    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (myInterrupted){
                    //这个线程就会一直运行
                    System.out.println("hello");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        Thread.sleep(10000);
        myInterrupted = false;
    }
}

hello
hello
hello
hello
hello
hello
hello
hello
hello
hello


主线程和我们创建的线程是并行的嘛,我们让创建的线程每个1秒打印hello,主线程先睡眠10秒,当创建的线程打印了10个hello后,主线程醒来了,修改了标志,这样创建的线程就不跑了.


Thread.interrupted()
重置标志位为false、并返回之前的标志位.

//boolean tmp = 标志位
//标志位 = false
//return tmp;

package package1129;

public class StopThread {
    public static void main(String[] args) {
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    //boolean tmp = 标志位
                    //标志位 = false
                    //return tmp;
                    boolean b = Thread.interrupted();
//                    boolean b = Thread.currentThread().isInterrupted();
                    System.out.println(b);
                }
            }
        });
        thread2.start();
        thread2.interrupt();
    }
}

true
false
false
false
false
false
false
false
false
false


2.Thread.currentThread().isInterrupted();

package package1129;

public class StopThread {
    public static void main(String[] args) {
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
//                    boolean b = Thread.interrupted();
                    boolean b = Thread.currentThread().isInterrupted();
                    System.out.println(b);
                }
            }
        });
        thread2.start();
        thread2.interrupt();
    }
}

true
true
true
true
true
true
true
true
true
true


1. 通过 thread 对象调用 interrupt() 方法通知该线程停止运行
2. thread 收到通知的方式有两种:
	2.1. 如果线程调用了 wait/join/sleep 等方法而阻塞挂起,
	则以 InterruptedException 异常的形式通知,清除中断标志
	2.2 否则,只是内部的一个中断标志被设置,thread 可以通过
		2.2.1. Thread.interrupted() 判断当前线程的中断标志被设置,
		清除中断标志
		2.2.2. Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,
		不清除中断标志
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值