Java多线程核心技术-1
如题:《Java多线程核心技术》笔记
isAlive:判断线程是否处于活动状态(已经启动,尚未终止)
停止线程
使用interrupte(),判断,异常来停止线程
package MultiThread.ch1;
public class ThreadStopTest {
public static void main(String[] args) {
try{
MyThread03 myThread03 = new MyThread03();
myThread03.start();
Thread.sleep(10);
myThread03.interrupt();//标记mythread03为停止状态
}catch (InterruptedException e){//这里捕捉的Interrupted方法是有sleep抛出的.
//什么时候sleep会抛出InterruptedException呢。
//当前线程处于休眠状态(阻塞状态等等其他非运行状态),而有另外的线程标记了当前状态为停止状态。则抛出异常。由当前线程自己捕获并做些线程被中断后的处理。在异常抛出之后,会清楚当前线程的停止标志。
e.printStackTrace();
System.out.println("进入main方法的catch语句");
}
System.out.println("main end");
}
}
class MyThread03 extends Thread{
@Override
public void run() {
try{
for (int i = 0; i <5000 ; i++) {
if(this.isInterrupted()){//在运行过程中判断是否停止
System.out.println("我被别人标记了停止,需要退出");
throw new InterruptedException();//如果停止了则抛出异常,必变执行for下面的语句
}
System.out.println(i+"");
}
System.out.println("我在for下面");
}catch (InterruptedException e){
System.out.println("进Mythread的catch方法了");//捕捉异常,可以进行一些资源的关闭。在这里并不比要求必须使用InterruptedException,使用其他的异常一样可以完成停止线程的动作。只不过InterruptedException比较合乎线程被外部标记为Interrupted的环境。
//线程也可以自己在run方法内部来使用interrupte方法来标记自己。
}
}
}
在沉睡中停止:
当前线程先调用Thread.currentThread().sleep()
之后外部标记:thread.interrupted()会抛出异常
在停止中沉睡:
外部先标记为interrupte(),线程不会立即停止。
当线程运行至sleep()的时候,会抛出异常
使用stop方法停止线程
有的时候使用stop方法会抛出ThreadDeatch异常,但通常不需要显示的捕捉。
stop方法已经被废弃。废弃的原因是:
- stop终止线程后,一些清理性的工作没有办法做到。
- stop会导致线程释放其拥有的锁。但是有可能在终止的时候,关于对象的状态的更新的操作还没有完全执行完,因此会导致数据不一致。(个人感觉不只stop会导致数据不一致的问题,其他的停止方式也会。但是可能由于其他的停止方式的会有异常处理这个部分,所以会对数据不一致的情况重新处理???)
使用return方法停止线程
使用interrupted和return方法来停止线程。在捕捉到停止标记之后,就返回。
总结
使用异常的方法停止线程,可以在catch块中对异常的信息进行相关处理
暂停线程
suspend和resume
suspend暂停线程,resume恢复线程的执行
package MultiThread.ch1;
public class ThreadSuspend {
public static void main(String[] args) {
try{
MyThread04 myThread04 = new MyThread04();
myThread04.start();
Thread.sleep(1000);
//
System.out.println("A_____暂停____");
myThread04.suspend();
System.out.println(myThread04.getI());
Thread.sleep(2000);
System.out.println(myThread04.getI());
//
System.out.println("B______恢复___");
myThread04.resume();
Thread.sleep(1000);
//
System.out.println("C______暂停___");
myThread04.suspend();
System.out.println(myThread04.getI());
Thread.sleep(2000);
System.out.println(myThread04.getI());
}catch (Exception e){
e.printStackTrace();
}
}
}
class MyThread04 extends Thread{
private long i=0;
public long getI() {
return i;
}
public void setI(long i) {
this.i = i;
}
@Override
public void run() {
while (true){
i++;
}
}
}
从输出结果可以验证线程的暂停和恢复。
suspend和resume方法为什么被废弃
suspend和resume方法的缺点——独占
在一个线程在suspend之后,并不会释放锁。所有其他需要想同锁的线程将会继续等待。
package MultiThread.ch1;
/**
* 关于suspend持有锁
*/
public class ThreadSuspend02 {
public static void main(String[] args) {
try {
final SynchronizeObject synchronizeObject = new SynchronizeObject();
Thread thread1 = new Thread(){
@Override
public void run() {
super.run();
synchronizeObject.printString();
}
};
thread1.setName("A");
thread1.start();
Thread.sleep(1000);
Thread thread2 = new Thread(){
@Override
public void run() {
System.out.println("线程B启动了,准备使用printString()方法");
synchronizeObject.printString();
}
};
thread2.setName("B");
thread2.start();
Thread.sleep(2000);
//thread1.resume();//如果不让线程A恢复执行,则线程A会一直持有锁,线程B不会执行printString()方法。如果恢复执行,线程A释放之后,线程B会获得锁,并运行。
} catch (Exception e) {
e.printStackTrace();
}
}
}
class SynchronizeObject{
synchronized public void printString(){
System.out.println("begin");
if(Thread.currentThread().getName().equals("A")){
System.out.println("当前线程为A线程,A线程暂停了");
Thread.currentThread().suspend();
}
System.out.println("end");
}
}
注释resume之后
取消resume的注释
其实个人觉得,这是线程的使用者没有完善的设计程序的原因造成的。并不是suspend的原因。
还有一种独占锁情况需要格外注意。
package MultiThread.ch1;
public class ThreadSuspend03 {
public static void main(String[] args) {
try{
MyThread06 myThread06 = new MyThread06();
myThread06.start();
Thread.sleep(3000);
myThread06.suspend();
System.out.println("main end");//main方法会输出吗???
}catch (Exception e){
e.printStackTrace();
}
}
}
class MyThread06 extends Thread{
private int i = 0;
@Override
public void run() {
while(true){
System.out.println(i++);
}
}
}
main end不会输出
为什么main end不会打印?println方法出现什么问题了吗?
/**
* Prints an integer and then terminate the line. This method behaves as
* though it invokes <code>{@link #print(int)}</code> and then
* <code>{@link #println()}</code>.
*注意这里有个锁,锁住了当前的输出流。因此在main方法中想要打印main end的时候,thread并没有释放输出流的锁。所以不能打印。
* @param x The <code>int</code> to be printed.
*/
public void println(int x) {
synchronized (this) {
print(x);
newLine();
}
}
suspend和resume方法的缺点——不同步
这种情况很类似stop方法造成的数据不一致。个人感觉这个也还是需要程序员去控制的。
其实关于suspend,resume,stop方法为什么废弃,大家可以参考
https://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html