• 2-Java线程(Thread)的常用方法


    常用方法

    方法名 static 功能说明 注意
    start() 启动一个新线 程,在新的线程运行 run 方法中的代码 start() 方法只是让线程进入就绪,里面代码不一定立刻运行(CPU 的时间片还没分给它)。每个线程对象的 start方法只能调用一次,如果调用了多次会出现 IllegalThreadStateException
    run() 新线程启动后,内部调用的方法 如果在构造 Thread 对象时传递了 Runnable 参数,则线程启动后会调用 Runnable 中的 run 方法,否则默认不执行任何操作。但可以创建 Thread 的子类对象, 来覆盖默认行为
    join() 等待线程运行结束
    join(long n) 等待线程运行结 束,最多等待 n 毫秒
    getId() 获取线程长整型的 id id 唯一
    getName() 获取线程名
    setName(String) 修改线程名
    getPriority() 获取线程优先级
    setPriority(int) 修改线程优先级 java中规定线程优先级是1~10 的整数,较大的优先级 能提高该线程被 CPU 调度的机率
    getState() 获取线程状态 Java 中线程状态是用 6 个 enum 表示,分别为: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
    isInterrupted() 判断是否被打断 不会清除打断标记
    isAlive() 线程是否存活(还没有运行完 毕)
    interrupt() 打断线程 如果被打断线程正在 sleep、wait、join,会导致被打断的线程抛出 InterruptedException,同时打断标记会被清除;
    如果打断的是正在运行的线程,则会设置打断标记;
    park 的线程被打断,也会设置打断标记
    interrupted() static 判断当前线程是否被打断 会清除打断标记
    currentThread() static 获取当前正在执行的线程
    sleep(long n) static 让当前执行的线 程休眠n毫秒, 休眠时让出 cpu 的时间片给其它 线程
    yield() static 提示线程调度器 让出当前线程对 CPU的使用 主要是为了测试和调试

    演示

    start

    启动线程的方法,不做演示了,嘻嘻


    run

    run 方法是线程启动后,内部执行的方法,一般不要主动调用合格方法。

    如果在程序中主动调用了这个方法,则现成的任务就会在调用者所在的线程内执行。

    public static void main(String[] args) {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                log.debug("任务执行");
            }
        };
        t1.run();
        log.debug("do other things ...");
    }
    

    sleep

    顾名思义,就是睡眠,调用 Thread.sleep() 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞),睡眠结束线程恢复执行(但是不一定会立刻执行)。

    public static void main(String[] args) {
    
        Thread t1 = new Thread(() -> {
            log.debug("我睡了");
            try {
                Thread.sleep(TimeUnit.SECONDS.toMillis(5));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.debug("睡饱了");
        }, "t1");
        t1.start();
    }
    

    其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException,打断标记会被清除。


    yield

    参看这篇文章:https://blog.csdn.net/dabing69221/article/details/17426953

    调用 yield 会让当前线程从 Running 进入 Runnable 状态,即让出 cpu 的使用权, 与其他同样是 Runnable 状态的线程一齐竞争 cpu 的使用权。

    public class YieldTest extends Thread {
    
        public YieldTest(String name) {
            super(name);
        }
    
        @Override
        public void run() {
            for (int i = 1; i <= 50; i++) {
                System.out.println("" + this.getName() + "-----" + i);
                // 当i为30时,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行)
                if (i == 30) {
                    this.yield();
                }
            }
        }
    
        public static void main(String[] args) {
            YieldTest yt1 = new YieldTest("张三");
            YieldTest yt2 = new YieldTest("李四");
            yt1.start();
            yt2.start();
        }
    }
    

    运行结果:

    第一种情况:李四线程当执行到30时,会让掉CPU时间片,这时张三(线程)抢到CPU时间并执行。

    img

    第二种情况:李四(线程)当执行到30时,会让掉CPU时间片,这时李四(线程)抢到CPU时间并执行。

    img


    join

    用于等待线程的结束,通常用在主线程等待其他线程的计算完成,主线程再运行。

    无超时等待,就嗯等:

    public static void main(String[] args) throws InterruptedException {
    
        Thread t1 = new Thread(() -> {
            log.debug("线程1开始");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a += 10;
            log.debug("线程2结束");
        });
        t1.start();
    
        // main线程等待 t1 运行结束
        t1.join();
    
        log.debug("主线程拿到的a是:{}", a);
    }
    

    有超时等待,等不到就算了:

    public static void main(String[] args) throws InterruptedException {
    
        Thread t1 = new Thread(() -> {
            log.debug("线程1开始");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a += 10;
            log.debug("线程2结束");
        });
        t1.start();
    
        // main线程等待 t1 运行结束,单位是ms
        t1.join(1000);
    
        log.debug("主线程拿到的a是:{}", a);
    }
    

    interrupt

    虽然 interrupt 有打断的意思,但是执行了 interrupt() 线程依然会继续执行,我们重点关注的是线程的打断标记,未被打断是 true,被打断了是 false,根据这个打断标记,我们可以做出对应的逻辑。

    打断正常运行的线程

    打断标记会置为 true

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.debug("线程开始");
            while (true) {
                Thread current = Thread.currentThread();
                boolean interrupted = current.isInterrupted();
                if (interrupted) {
                    log.debug(" 打断状态: {}", interrupted);
                    break;
                }
            }
            log.debug("线程结束");
        }, "t1");
        t1.start();
        Thread.sleep(500);
        t1.interrupt();
    }
    

    打断 sleep,wait,join 的线程

    打断执行了或正在执行以上方法的线程,会导致被打断的线程抛出 InterruptedException,并且这些线程会进入阻塞状态 ,同时打断标记会被清除(置为false)。

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.debug("线程开始");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.debug("线程结束");
        }, "t1");
        t1.start();
        Thread.sleep(200);
        t1.interrupt();
        log.debug(" 打断状态: {}", t1.isInterrupted());
    }
    

    打断 park 的线程

    打断 park 线程,不会清除打断标记

        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> {
                log.debug("park...");
                LockSupport.park();
                log.debug("unpark...");
                log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
            }, "t1");
            t1.start();
            Thread.sleep(500);
            t1.interrupt();
        }
    

    park、unpark

    注意,这两个方法并不是 Thread 类的方法,而是 LockSupport 类中的方法,park 用于暂停当前线程,unpark 用于恢复指定线程。

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.debug("start...");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.debug("park...");
            LockSupport.park();
            log.debug("resume...");
        },"t1");
        t1.start();
        Thread.sleep(2000);
        log.debug("unpark...");
        LockSupport.unpark(t1);
    }
    

    如果执行 park 前,打断标记已经是 true,那么 park 将会失效

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            // 1~4的循环时,park会失效
            for (int i = 0; i < 5; i++) {
                log.debug("park {}...", i);
                LockSupport.park();
                log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
            }
        }, "t1");
        t1.start();
    
        Thread.sleep(1000);
        t1.interrupt();
    }
    

    不推荐使用的方法

    这些方法已过时,使用起来很容易破坏同步代码块,造成线程死锁

    方法名 static 功能说明
    stop() 停止线程运行
    suspend() 挂起(暂停)线程运行
    resume() 恢复线程运行
  • 相关阅读:
    c#基础之Type
    .Net IOC框架入门之三 Autofac
    EF的三种数据加载方式
    EntityFramework扩展之第三方类库
    EF Codefirst入门之创建数据库
    EasyUI combotree的使用
    MacOS 安装 gdb 踩过的坑
    enex 转 md 格式的几种方式(免费版/氪金版)
    C++ 标准库之 iomanip 、操作符 ios::fixed 以及 setprecision 使用的惨痛教训经验总结
    python list 中 remove 的骚操作/易错点
  • 原文地址:https://www.cnblogs.com/sout-ch233/p/14315665.html
Copyright © 2020-2023  润新知