线程的操作

线程的操作

1.启动一个线程
覆写run方法创建一个线程对象,对象被创建出来并不意味着线程就开始运行了
run()方法相当于提供给线程要做的事情的清单。
线程对象可以认为是让线程准备好,调用过来。
这时候调用start()方法,就可以使线程执行起来了。

在这里插入图片描述
中断一个线程
线程一旦进入到工作状态,就会按照run()方法中的程序去执行,不完成不会结束。
但是有时候要增加一些机制,让正在运行的线程停止下来。

让线程停止的方式:
1.通过共享的标记来进行沟通
2.通过interrupt()(打断)方法来通知

//停止线程的方式
public class ThreadDemo {
    private static class MyRunnable implements Runnable{
        //volatile修饰变量,不允许线程内部缓存和重排序,也就是直接修改内存
        //定义线程初始为不主动放弃状态
        public volatile boolean isQuit=false;
        @Override
        public void run() {
            while(!isQuit){
                System.out.println(Thread.currentThread().getName()+":我正在运行");
                try {
                    //定义每1秒休眠一次
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+":停下来了");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target=new MyRunnable();
        //创建线程对象并且命名为小代
        Thread thread=new Thread(target,"小代");
        System.out.println(Thread.currentThread().getName()+":让小代这个线程开始运行");
        thread.start();
        //定义每10秒休眠一次
        Thread.sleep(10*1000);
        System.out.println(Thread.currentThread().getName()+":让小代这个线程停止运行");
        //让线程初始状态变为不运行,就不执行run()方法了。
        target.isQuit=true;
    }
}
/*
执行结果:
main:让小代这个线程开始运行
小代:我正在运行
小代:我正在运行
小代:我正在运行
小代:我正在运行
小代:我正在运行
小代:我正在运行
小代:我正在运行
小代:我正在运行
小代:我正在运行
小代:我正在运行
main:让小代这个线程停止运行
小代:停下来了

 */

volatile修饰变量,不允许线程内部缓存和重排序,也就是直接修改内存

/停止线程的方式
//调用interrupt()方法来通知
public class ThreadDemo2 {
    private static class MyRunnable implements Runnable{
        @Override
        public void run() {
            while(!Thread.interrupted()){
                System.out.println(Thread.currentThread().getName()+":别管我,我正在干活");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println(Thread.currentThread().getName()+":有情况,现在停止线程");
                    break;
                }
            }
            System.out.println(Thread.currentThread().getName()+":停下来了");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyRunnable target=new MyRunnable();
        Thread thread=new Thread(target,"小代");
        System.out.println(Thread.currentThread().getName()+":让小代开始工作");
        thread.start();
        Thread.sleep(10*1000);
        System.out.println(Thread.currentThread().getName()+":让小代停下来");
        thread.interrupt();
    }
}
/*
执行结果:
main:让小代开始工作
小代:别管我,我正在干活
小代:别管我,我正在干活
小代:别管我,我正在干活
小代:别管我,我正在干活
小代:别管我,我正在干活
小代:别管我,我正在干活
小代:别管我,我正在干活
小代:别管我,我正在干活
小代:别管我,我正在干活
小代:别管我,我正在干活
main:让小代停下来
java.lang.InterruptedException: sleep interrupted
小代:有情况,现在停止线程
	at java.lang.Thread.sleep(Native Method)
小代:停下来了
	at 多线程复习2.ThreadDemo2$MyRunnable.run(ThreadDemo2.java:13)
	at java.lang.Thread.run(Thread.java:748)

 */

通过Thread对象调用Interrupt方法通知该线程停止运行
thread收到通知的方法有两种:
1.如果线程调用了 wait/join/sleep 等 方法而阻塞挂起,则以interruptedException异常的形式通知,清除中断标志。
2.否则只是内部的一个中断标志被设置thread可以通过
1、Thread.interrupted判断当前线程的中断标志被设置,清除中断标志。
2、Thread.currentThread().isInterrupted()判断指定线程的中断标志被设置,不清除中断标志。
使用interrupt通知,线程会收到的更及时,即时在sleep状态也能马上收到。

如果线程调用了sleep、wait、join等方法,主线程通过interrput的方法通知该线程,以interruptedException异常形式通知,并且会清除中断标志。
如果线程没有调用上面的方法,那么就只是内部的一个中断标志被设置。
1、thread如果通过Thread.interrupted判断当前线程的中断标志,判断完成之后中断标志就会被清除。
2、thread如果通过Thread.currentThread.interruoted判断当前线程的中断标志,只是判断一下,并不会清除。

/线程sleep,通过异常收到了中断的情况
public class ThreadDemo3 {
    private static class MyRunnable implements Runnable{
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("通过异常收到了中断情况");
            }
            for (int i = 0; i <10 ; i++) {
                System.out.println(Thread.currentThread().isInterrupted());
            }
        }
    }
    public static void main(String[] args) {
        MyRunnable target =new MyRunnable();
        Thread thread=new Thread(target,"小代");
        thread.start();
        thread.interrupt();
    }
}
/*
执行结果:
false
false
false
false
false
false
false
false
false
false
public class ThreadDemo4 {
    private static class MyRunnable implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i <10 ; i++) {
                System.out.println(Thread.interrupted());
            }
        }
    }
    public static void main(String[] args) {
        MyRunnable target=new MyRunnable();
        Thread thread=new Thread(target,"小代");
        thread.start();
        thread.interrupt();
    }
}
/*
执行结果:
true   一开始是true,,后边的标志位都被清除了,所以是false
false
false
false
false
false
false
false
false
false

 */
public class ThreadDemo5 {
    private static class MyRunnbale implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread .currentThread().isInterrupted());
            }
        }
    }
    public static void main(String[] args) {
        MyRunnbale target=new MyRunnbale();
        Thread thread=new Thread(target,"小代");
        thread.start();
        thread.interrupt();
    }
}
/*
执行结果:
true   全部是true,因为标志位没有被清除
true
true
true
true
true
true
true
true
true
 */

调用一个线程的interrupt() 方法中断一个线程,并不是强行关闭这个线程,只是跟这个线程打个招呼,将线程的中断标志位置为true,线程是否中断,由线程本身决定。

isInterrupted() 判定当前线程是否处于中断状态。

static方法interrupted() 判定当前线程是否处于中断状态,同时中断标志位改为false。

方法里如果抛出InterruptedException,线程的中断标志位会被复位成false,如果确实是需要中断线程,要求我们自己在catch语句块里再次调用interrupt()。

在这里插入图片描述

等待一个线程join()

有的情况下,我们需要等待一个线程执行完成之后,才能进行下一步的工作。这个时候我们需要一个方法明确等待线程的结束。

/join,等待一个线程结束来执行下一个线程
public class JoinDemo {
    public static void main(String[] args) throws InterruptedException {
        Runnable target=()->{
            for (int i = 0; i <10; i++) {
                System.out.println(Thread.currentThread().getName()+":我还在工作!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+":我结束了!");
        };
        Thread thread1=new Thread(target,"小代");
        Thread thread2=new Thread(target,"小赵");
        System.out.println("让小代先开始工作");
        thread1.start();
        thread1.join();
        System.out.println("小代工作结束了,让小赵开始工作");
        thread2.start();
        thread2.join();
        System.out.println("小赵工作结束了");
    }
}
/*
执行结果:
让小代先开始工作
小代:我还在工作!
小代:我还在工作!
小代:我还在工作!
小代:我还在工作!
小代:我还在工作!
小代:我还在工作!
小代:我还在工作!
小代:我还在工作!
小代:我还在工作!
小代:我还在工作!
小代:我结束了!
小代工作结束了,让小赵开始工作
小赵:我还在工作!
小赵:我还在工作!
小赵:我还在工作!
小赵:我还在工作!
小赵:我还在工作!
小赵:我还在工作!
小赵:我还在工作!
小赵:我还在工作!
小赵:我还在工作!
小赵:我还在工作!
小赵:我结束了!
小赵工作结束了

在这里插入图片描述

获取当前线程的引用

public static Thread currentThread();

返回当前线程对象的引用。

public class Threaddemo{
	public static void main(String [] args){
		Thread thread=new Thread.currentThread();
		System.out.println(thread.getName());
	}
}

休眠当前线程

由于线程的调度是不可控制的,所以这个方法只能保证休眠时间是大于等于休眠时间的设定值。

在这里插入图片描述

public class main2 {
    public static void main(String[] args) throws InterruptedException {
        System.out.println(System.currentTimeMillis());
        Thread.sleep(3*1000);
        System.out.println(System.currentTimeMillis());
    }
}
/*
执行结果:
        1578991732704 
        1578991735704
*/

线程的状态

//获取线程的所有状态
public class ThreadState {
    public static void main(String[] args) {
        for(Thread.State state:Thread.State.values()){
            System.out.println(state);
        }
    }
}
/*
NEW       
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED
 */

线程的状态及状态转移的意义

在这里插入图片描述
当线程准备好去运行,等待服务,就进入到Runnable状态,这个状态包含正在执行的线程,也包含可被执行的线程,也就是正在排队的线程,是否开始执行,要看服务器的调度。

当线程等待其他外部事件的时候,会进入到BLOCK、WATING 、TIMED_WAITING状态

只要线程不是NEW状态和TREMINATED状态,那么线程都是活着的线程。也就是该线程调用isAlive()方法为true

观察线程的状态和转移

关注NEW、RUNNABLE、TERMINATED状态转换
public class ThreadStateTransfer {
    public static void main(String[] args) {
        Thread t=new Thread(()->{
            for (int i = 0; i <1000_0000 ; i++) {
            }
        },"小代");
        System.out.println(t.getName()+":"+t.getState());
        t.start();
        while(t.isAlive()){
            System.out.println(t.getName()+":"+t.getState());
        }
        System.out.println(t.getName()+":"+t.getState());
    }
}

关注 WAITING BLOCKED TIMED_WAITING状态的转换

public class ThreadStateTransfer2 {
    public static void main(String[] args) throws InterruptedException {
        Object object=new Object();
        Thread t=new Thread(()->{
            synchronized (object) {
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for (int i = 0; i < 1000_0000; i++) {
                }
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        System.out.println(t.getState());
        t.start();
        System.out.println(t.getState());
        Thread.sleep(10);
        synchronized (object){
            for (int i = 0; i <10; i++) {
                System.out.println(t.getState());
            }
            object.notify();
        }
        while (t.isAlive()){
            System.out.println(t.getState());
        }
    }
}

yield()方法

yield()只是让出CPU,并不会改变自己的状态,就是从正在运行的状态变成待运行的状态。

//yield()让出CPU
public class ThreadStateTransfer3 {
    public static void main(String[] args) {
        Thread thread1=new Thread(()->{
            while(true){
                System.out.println(Thread.currentThread().getName()+":我正在工作");
                //Thread.yield();
            }
        },"小代");
        Thread thread2=new Thread(()->{
            while(true){
                System.out.println(Thread.currentThread().getName()+":我正在工作");
            }
        },"小赵");
        thread1.start();
        thread2.start();
    }
}
//打印出来小赵的工作多于小代的工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值