回顾:
线程和进程的区别
线程的创建:
1.继承Thread类(单继承)[2种]
2.继承Runnable run[3种]
3.jdk 1.5 实现Callable +futureTask
线程的构造方法:
1.设置线程名
2.设置线程任务
3.设置线程分组
线程的常用属性:
ID
Name
状态
优先级(1~10,默认5)
守护线程(后台线程)
线程的分类
守护线程
用户线程(main)
守护线程需要注意的事项:
1.守护线程设置必须在调用start之前();
如果设置守护线程在开始线程之后,那么程序就会报错,并且设置的守护线程值不能生效。
2在守护线程里面创建的线程,默认情况下全部都是守护线程
start和run区别:
1.run属于普通方法,start属于启动线程的方法
2.run方法可以执行多次,而start方法只能执行一次
线程中断:
1.使用全局自定义的变量来终止线程
2.使用线程提供的终止方法 interrupt来终止线程
3.使用线程提供的方法stop来终止线程(已经不用)
t1.interrupt(); 终止线程
while(!Thread.interrupted()) 判断线程的终止状态
使用全局自定义标识终止线程执行的时候比较温柔,当他收到了终止指令之后,会把当前手头的任务执行完再终止。使用interrupt会立马结束执行
两种实现线程中断的方法
第一种:使用全局自定义变量
/**
* 使用全局自定义变量来终止线程
*/
public class ThreadDemo17 {
// 全局自定义变量
private static boolean flag = false;
public static void main(String[] args) throws InterruptedException {
// 转账线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
while (!flag) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("别烦我,我正在转账呢");
}
System.out.println("终止转账");
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(310);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 改变变量的状态来终止线程的执行
System.out.println("停止交易,有内鬼。");
flag = true;
}
});
t2.start();
t1.join();
t2.join();
}
}
第二种:使用interrupt终止线程
public class ThreadMain19 {
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
// while(!Thread.interrupted()){
while(!Thread.currentThread().isInterrupted()){
System.out.println("别烦我,正转账呢");
}
System.out.println("终止线程");
}
});
t1.start();
Thread.sleep(10);
System.out.println("有内鬼,终止交易");
t1.interrupt();
}
}
while(!Thread.interrupted()) //执行结束状态自动复位为false
执行判断线程终止为true之后就会将状态重置为false
while(!Thread.currentThread().isInterrupted()) 不会复位线程的终止状态
interrupted()和isInterrupt()区别:
interrupted()是全局的方法,他判断完之后会重置线程的状态
interrupt 方法的作用就是将线程中的终止状态从默认的false改为true
等待线程程序完成
- t1.join()
- while(!t1.isAlive())
线程状态
NEW---------------------新建状态,没有调用线程start()之前的状态
RUNNABLE------------运行状态(Running执行中,ready就绪)
BLOCKED--------------阻塞状态
WAITING---------------等待,没有明确的等待结束时间wait()
TIMED_WAITING----超时等待状态,有明确的等待结束时间,比如sleep(xxx)
TERMINATED--------终止状态
yield方法:出让CPU执行权,特点是不一定能真正的出让CPU的执行权
Thread.yield();出让CPU的执行权
多线程风险:
线程不安全:多线程执行中,程序的执行结果和预期不相符就叫线程不安全
++/–操作
1.load(读取)
2calc(运算)
3.save(保存)
并行操作
t1.join();
t2.join();
线程非安全原因:
1.CPU抢占执行(万恶之源);
2.非原子性;
3.编译器优化(代码优化);
**编译器优化在单线程下没问题,可以提升程序执行效率,但在多线程下就会出现混乱,从而导致线程不全的问题。
4.(内存)不可见性问题;
5.多个线程修改了同一个变量