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() 判断指定线程的中断标志被设置,
不清除中断标志
本文探讨了Java中Thread类的中断机制,包括join方法如何使主线程等待子线程完成,yield方法如何让当前线程放弃CPU执行权,以及如何通过中断标志来控制线程的执行。通过示例展示了线程状态的变化和中断操作的效果。
1万+

被折叠的 条评论
为什么被折叠?



