java实现多线程的方式
- 继承Thread类
- 实现Runnable接口
线程共享数据
重写Thread实现
public class MyThread extends Thread {
private int count=5;
@Override
public void run() {
super.run();
while(count>0){
count--;
System.out.println(Thread.currentThread().getName()+":"+count);
}
}
}
调用:
MyThread thread = new MyThread();
Thread threadA = new Thread(thread, "A");
Thread threadB = new Thread(thread, "B");
Thread threadC = new Thread(thread, "C");
Thread threadD = new Thread(thread, "D");
threadA.start();
threadB.start();
threadC.start();
threadD.start();
结果:
A:3
C:2
B:3
C:0
A:1
说明A、B线程同时对count进行处理,产生了非线程安全问题,两个线程同时读取到了count为同一个值的情况。
解决
在方法前加上synchronized
synchronized public void run()
结果:
A:4
A:3
A:2
A:1
A:0
效果是在多线程执行run方法的时候,以排队的方式进行处理。当一个线程调用run前,判断run是否加锁,如果加锁了,则一直循环等待锁被释放。synchronized可以在任意对象以及方法上加锁,而加锁的这段代码称为“互斥区”,“临界区”
“非线程安全”:多个线程对同一个对象中的同一个实例变量进行操作时出现值被更改、值不同步的情况。
//返回当前执行的线程名称
Thread.currentThread().getName()
//必须在Thread中使用,返回这个Thread的名称
this.getName();
Thread方法
- isAlive():判断当前线程是否处于活动状态
活动状态:线程已经启动尚未终止,处于正在运行或者准备开始的状态
注意点:
//这里thread线程执行myThread,所以myThrad isAlive为false,从未启动,
//启动的是thread 他的isAlive为true。
MyThread myThrad=new MyThread();
Thread thread=new Thread(myThread);
thread.start
- sleep():在指定毫秒内让当前执行的线程休眠
这线程是指this.currentThread()的线程。 - getId():获取线程的唯一标识
在主线程中执行Thread.currentThread.getId()结果为1 停止线程
(一):使用退出标志,使线程正常退出。
(二):stop()强制终止,不推荐使用
(三):interrupt()中断线程,只是设置了状态,具体的终止还是要自己实现判断线程是否已经停止了
1.this.interrupted():判断当前线程是否已经中断
测试调用this.interrupted()的线程是否已经中断,执行后可以清除中断标志
//如果在main方法里面调用这个,表示判断main线程是否已经中断
thread.interrupted();
2.this.isInterrupted():判断线程是否已经中断
测试线程Thread对象是否已经中断,不能清除中断标志
停止线程-异常法
在线程run方法中
public void run(){
try{
if(this.interrupted){
throw new InterruptedException();
}
}catch(InterruptedException e){
system.out.println("线程中断,退出");
}
}
//调用
//调用的时候这是线程对象为中断,线程run方法判断如果是中断状态,则异常,然后捕获退出。
thread.interrupt();
停止线程-睡眠法
//线程中断遇上sleep()则会自动抛出InterruptedException()异常
//run方法内部
Thread.sleep(10000000)
//调用线程
thread.interrupt();
停止线程-暴力停止
调用stop()方法会抛出ThreadDeath异常,stop()已经作废,因为如果强制让线程停止则有可能使一些清理性的工作得不到完成,另外对锁定的对象进行解锁,导致数据同步不一致。
比如,正在执行synchronized的方法,线程已经获得了锁,原本需要执行完成才释放,遇到stop的时候,直接释放的锁,导致数据不一致,
例子synchronized的内部做了两件事 赋值 a=2, b=3,执行一半就会出现a已经等于2了但是b还是空的结果出现。
//直接停止线程
thread.stop
- 暂停线程
suspend:暂停
resume:恢复
容易造成公共同步对象的独占,使其他线程无法访问公共同步对象
也容易出现因为线程暂停而导致数据不同步的情况 - yield():
放弃当前CPU字段,给其他任务去执行,但是放弃时间随机,有可能刚放弃,又马上获得CPU时间片 - 线程优先级(setPriority()):
优先级越高,越容易先执行(也有随机性),等级分为1-10。优先级有继承性,如果A线程执行了B线程,则B线程和A线程的优先级一样
守护线程
Java线程有两种:用户线程,守护线程
如果非守护线程不存在,则守护线程自动销毁。
//设置为守护线程
thread.setDaemon(true);