likes
comments
collection
share

(二)并发-线程的操作

作者站长头像
站长
· 阅读数 16

设置线程的名称

/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[9:53 AM]  
* @Desc 设置线程的名称 也可以在构造中直接设置
*/  
public class SettingThreadName {  
    public static void main(String[] args) {  
        Thread thread = new Thread(() -> System.out.println("设置线程的名称测试"));  
        thread.setName("我的线程名称");  
        thread.start();  
        System.out.println(thread.getName());  
    }  
}

设置线程组的名称

/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[9:53 AM]  
* @Desc 设置线程组的名称  
*/  
public class SettingThreadGroupName {  
    public static void main(String[] args) {  
        Thread thread = new Thread(new ThreadGroup("我是线程组的名称"), () -> {  
        System.out.println("测试线程组的名称");  
        });  
        thread.start();  
        System.out.println(thread.getThreadGroup().getName());  
    }  
}

线程的优先级

/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[10:05 AM]  
* @Desc 设置线程的优先级 setPriority 线程默认有10个级别 1最小 10 最大 默认 5
* 优先级越高 优先获得CPU执行权的机会就越高
*/  
public class SettingThreadPriority {  
    public static void main(String[] args) {  
        Thread thread1 = new Thread(() -> {System.out.println("线程1");},"thread1");  
        Thread thread2 = new Thread(() -> {System.out.println("线程2");},"thread2");  
        thread1.setPriority(1);  
        thread2.setPriority(10);  
        thread1.start();  
        thread2.start();  
    }  
}

线程启动

使用Thread类的 public synchronized void start() 该方法表示线程处于可运行状态,可以获取CPU调度进行执行的权利

线程休眠

//线程休眠 millis 毫秒数 放弃CPU执行权,时间一到,重新争抢CPU的执行权
Thread sleep(long millis) throws InterruptedException
//线程休眠 millis 毫秒数 + nanos 纳秒数 放弃CPU执行权,时间一到,重新争抢CPU的执行权
public static void sleep(long millis, int nanos) throws InterruptedException 
/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[10:15 AM]  
* @Desc 线程休眠  
*/  
public class ThreadSleep {  
public static void main(String[] args) throws InterruptedException {  
        Thread thread = new Thread(() -> System.out.println("当前时间"+ LocalTime.now()));  
        thread.start();  
        Thread.sleep(5000);  
        System.out.println("结束时间"+LocalTime.now());  
    }  
}

线程中断 interrupt()

当线程被 wait(), sleep(), join() 方法修饰阻塞的时候,调用当前线程的interrupt()方法会被抛出InterruptedException异常,当前线程的中断标记会被清除,需要手动捕获并处理异常,并重新设置中断标记位置,保证其他线程可知当前线程的中断状态,保证程序的正常执行。

/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[10:28 AM]  
* @Desc 线程中断  
*/  
public class ThreadInterrupt2 {  
    public static void main(String[] args) {  
        Thread thread = new Thread(()->{  
        for (int i = 0; i < 100; i++) {  
            System.out.println(i);  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException e) {  
                System.out.println("线程不该运行了需要进行停止 InterruptedException"); 
                //重新设置标记位置  
                Thread.currentThread().interrupt();  
                break;  
            }  
            }  
        },"Thread1");  
        thread.start();  
        thread.interrupt();  
        System.out.println(thread.isInterrupted());  
        System.out.println("线程执行完成");  
    }  
}

线程中断interrupt()

当线程在运行过程中被 interrupt() ,当前线程的中断标记会被设置为true,此时需要使用public boolean isInterrupted()判断当前线程是否被中断,如果被中断,则结束当前程序。

/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[10:28 AM]  
* @Desc 线程中断  
*/  
public class ThreadInterrupt {  
    public static void main(String[] args) throws InterruptedException {  
        Thread thread = new Thread(()->{  
        for (int i = 0; i < 100; i++) {  
                if( Thread.currentThread().isInterrupted() ){  
                    System.out.println(i);  
                    System.out.println("线程被中断了");  
                    break;  
                }  
            }  
        });  
        thread.start();  
        thread.interrupt();  
        Thread.sleep(1000);  
        System.out.println("线程执行完成");  
    }  
}

等待通知

等待通知是在synchronized修饰时使用Object类中的wait(),notify(),notifyAll()进行实现wait()方法会释放持有的锁对象进入阻塞,如果不进行唤醒,会一致处于该状态。而且锁对象必须是同一把锁

/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[11:30 AM]  
* @Desc 线程的等待通知唤醒  
*/  
public class ThreadNotice {  
    public static void main(String[] args) throws InterruptedException {  
        Thread thread = new Thread(() -> {  
            synchronized (ThreadNotice.class){  
                try {  
                System.out.println("调用wait()等待唤醒");  
                ThreadNotice.class.wait();  
                System.out.println("已经被唤醒了");  
                } catch (InterruptedException e) {  
                e.printStackTrace();  
                }  
            }  
        });  
        thread.start();  
        Thread.sleep(1000);  
        //可以使用notifyAll()  
        synchronized (ThreadNotice.class){ThreadNotice.class.notify();}  
    }  
}

线程挂起

当线程调用 suspend()方法 会导致线程被挂起,停止执行,并且不会释放当前所持有的锁资源,直至调用resume() 方法使线程继续执行,否则造成资源一直被占用,官方已经废弃该方法,建议使用中断标记,suspend 容易引起死锁。如果使用了 suspend 的线程持有锁资源,其他线程都不可访问该资源。如果其他线程在 resume 之前试图锁定这个监视器,就会发生死锁。也称之为 冻结 进程

/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[11:45 AM]  
* @Desc 线程挂起  
*/  
public class ThreadSuspend {  
    public static void main(String[] args) throws InterruptedException {  
        Thread thread = new Thread(() -> {  
        synchronized (ThreadSuspend.class){  
                System.out.println("当前线程被挂起");  
                Thread.currentThread().suspend();  
                System.out.println("当前线程唤醒继续执行");  
            }  
        });  
        thread.start();  
        Thread.sleep(2000);  
        thread.resume();  
    }  
}

等待让步

线程调用join()方法是其他线程等待当前线程执行完成,其中底层是以wait()实现的,所以join()方法使被synchronized修饰

/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[11:58 AM]  
* @Desc 等待执行  
*/  
public class ThreadJoin {  
    public static void main(String[] args) throws InterruptedException {  
        Thread thread1 = new Thread(() -> {  
            System.out.println("T1线程正在运行");  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException e) {  
            e.printStackTrace();  
            }  
        },"T1");  
        Thread thread2 = new Thread(() -> {  
            System.out.println("T1线程完成T2运行");  
        },"T2");  
        thread1.start();  
        thread2.start();  
        System.out.println("T2等待T1执行完成");  
        thread1.join();  
    }  
}

线程调用yield()方法,会释放当前所持有的资源,以供其他线程优先进行执行,其当前线程会进入获取资源的队列中。

/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[12:07 PM]  
* @Desc 线程让步  
*/  
public class ThreadYield {  
    public static void main(String[] args) {  
        Thread thread = new Thread(() -> {  
            for (int i = 0; i < 100; i++) {  
                System.out.println(i);  
                if( i == 3)  
                    Thread.yield();  
            }  
        },"T1");  
        Thread thread2 = new Thread(() -> System.out.println("T2开始执行了"),"T2");  
        thread.start();  
        thread2.start();  
    }  
}

守护终止

线程非为用户线程和守护线程,用户线程需要全部执行完成才可以,main() 也是用户线程,守护线程则不需要,虚拟机在停止运行的时候,用户线程需要全部执行完成,而守护线程则不一定,通过 setDaemon(true) 设置当前线程为守护线程,注意,必须在start()方法之前设置,否则会抛出IllegalThreadStateException异常,默认是非守护线程

/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[12:15 PM]  
* @Desc 线程守护  
*/  
public class ThreadDaemon{  
    public static void main(String[] args) {  
        Thread thread1 = new Thread(() -> {  
            System.out.println("T1线程正在运行");  
        },"T1");  
        Thread thread2 = new Thread(() -> {  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            System.out.println("为T1的守护线程");  
            IntStream.range(0,100).forEach(System.out::println);  
        },"T2");  
        thread1.start();  
        thread2.setDaemon(true);  
        thread2.start();  
        System.out.println("程序结束了");  
    }  
}

线程的终止是通过 stop() 方法来实现的,不论线程是否执行完成,调用该方法会立刻终止线程,包括在 catchfinally 语句中的 ,已经废弃,建议使用中断标志进行停止线程, 可能会导致任务清理工作无法完成,如文件流,数据库指针等的关闭。同时会释放该线程所有的资源监视器,由于任务执行状态不可知,导致该线程所持有的资源状态不确定,可能出现数据不一致的问题。

/**  
* @Author 尘心[ZcJ]  
* @Date [2023/4/27]-[12:29 PM]  
* @Desc 线程终止  
*/  
public class ThreadStop {  
    public static void main(String[] args) {  
        Thread thread2 = new Thread(() -> System.out.println("线程2开始执行"));  
        thread2.start();  
        thread2.stop();  
    }  
}