JAVA多线程编程核心技术-1

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方法已经被废弃。废弃的原因是:

  1. stop终止线程后,一些清理性的工作没有办法做到。
  2. 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之后
取消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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值