多线程
Posted Kirl z
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程相关的知识,希望对你有一定的参考价值。
多线程(二)
1. Thread 类基础 api
修饰符和类型 | 方法和描述 |
---|---|
static Thread | currentThread() 返回对当前正在执行的线程对象的引用 |
static void | sleep(long millis) 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。 |
static void | yield() 对调度程序的一个暗示,即当前线程愿意产生当前使用的处理器。 |
static int | activeCount() 返回当前线程的thread group及其子组中活动线程数的估计。 |
public class ThreadDemo {
public static void main(String[] args) {
Thread thread = Thread.currentThread();
System.out.println(thread.getName());
}
}
2. 理解多线程效率与线程数, 任务量, 系统可用资源的关系
通过控制变量法测试
如何确定线程数?
总任务量恒定, 系统可用资源恒定的情况下:
线程创建是比较耗时的操作, 单个任务量比较小, 还不如一个线程就完成, 不用开启新的线程
public class ThreadAdv {
public static void main(String[] args) {
//循环10亿次,每次++运算
//1.串行的方式:main线程运行两次
long start = System.nanoTime();
loop();
loop();
long end = System.nanoTime();
System.out.printf("串行执行耗时:%s毫秒%n", (end-start)/1000/1000);
//2.并行的方式:main线程,子线程同时执行loop方法
long start2 = System.nanoTime();
new Thread(new Runnable() {
@Override
public void run() {
loop();
}
}).start();
loop();
//计算时间,需要让子线程,main线程loop都执行完
//当前main和main线程中创建的子线程,活跃线程数>1,main线程就一直让步
//子线程执行完,main线程才能继续向下执行
//使用activeCount在idea要用debug方式运行
while(Thread.activeCount()>1) Thread.yield();
long end2 = System.nanoTime();
System.out.printf("并行执行耗时:%s毫秒%n", (end2-start2)/1000/1000);
}
private static void loop(){
int m = 0;
for (int i = 0; i < 10_0000_0000; i++) {
m++;
}
}
}
3. 线程中断
3.1 使用(共享)标志位
可以实现某种程度上的, 在满足条件 (中断线程的条件: 如转账发现诈骗) 情况下, 中断一个线程
public class FlagStopThread {
//使用标志位标识是否继续执行线程中的任务,true中断,false继续执行
private static volatile boolean isStop = false;
public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("开始转账");
try {
while (!isStop){
System.out.println("转账ing...");
Thread.sleep(10000);
}
System.out.println("停止转账");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(3*1000);
//发现是诈骗犯,需要停止转账
isStop = true;
}
}
但存在问题:
如果一个线程正处于阻塞状态 (需要满足一定条件如sleep休眠一定时间, 才能恢复), 就无法快速 (立即) 的中断线程
3.2 调用 interrupt() 方法
Thread 类中, 保存有一个中断表示为, 初始值 = false (没有被中断)
类型 | 描述 |
---|---|
void | interrupt() 中断这个线程 |
中断某个线程:
- 线程中断标志位 = true
- 线程要不要中断, 线程定义任务的代码自行决定
- 如果线程处于阻塞状态 (调用多线程阻塞 api 方法, 显示抛出 InterruptedException 的方法)
直接提前让线程从阻塞状态转变为就绪态, 在系统调度执行后, 以抛异常的方式继续执行 (此时线程的中断标志位会重置为 false)
public class InterruptedResetFlag {
public static void main(String[] args) {
test1();
test2();
}
public static void test1(){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
//标志位=true
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().isInterrupted());
}
//打印结果:10次true
}
});
t.start();
t.interrupt();//1,标志位=true
}
public static void test2(){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
//标志位=true
for (int i = 0; i < 10; i++) {
//i==0, 打印true,重置标志位=false
System.out.println(Thread.interrupted());
}
//打印结果:第一次true,后边9次false
}
});
t.start();
t.interrupt();//1,标志位=true
}
}
3.3 interrupted() 方法
线程可以获取中断标志位, 通过循环判断, 来决定是否需要中断
类型 | 描述 |
---|---|
static boolean | interrupted() 测试当前线程是否中断 |
boolean | isInterrupted() 测试这个线程是否被中断 |
public class InterruptThread {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("开始转账");
while (!Thread.currentThread().isInterrupted()){
System.out.println("转账ing...");
Thread.sleep(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(3*1000);
t.interrupt();
}
}
4. 线程等待
类型 | 描述 |
---|---|
void | join() 等待这个线程死亡 |
void | join(long millis) 等待这个线程死亡最多 millis 毫秒 |
线程引用对象 .join() / 线程引用对象.join(long)
当前线程等待, 知道满足…条件:
- 无参的方法, 就是线程执行完毕
- 有参的方法, 是线程执行完毕和时间到达任意一个满足
满足以后, 当前线程继续往下执行
public class ThreadJoin {
public static void main(String[] args) throws InterruptedException {
test1();
test2();
}
public static void test1() throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t run");
}
});
t.start();
t.join();//main线程一直阻塞等待,直到t线程执行完毕,main线程再继续执行
System.out.println("main running...");
}
public static void test2() throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("t start");
Thread.sleep(3000);
System.out.println("t end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
t.join(1000);//main线程一直阻塞等待,直到t线程执行完毕,main线程再继续执行
System.out.println("main running...");
}
}
5. 线程状态
Java 中线程的所有状态:
NEW (创建)
RUNNABLE (可运行态)
BLOCKED (阻塞态)
WAITING (等待)
TIMED_WAITING (超时等待)
TERMINATED (终止)
- yield() 只是让出 CPU,并不会改变自己的状态, 线程让步。
以上是关于多线程的主要内容,如果未能解决你的问题,请参考以下文章