JUC并发编程——线程的基本方法使用

目录

一、线程名称设置和获取

二、线程的sleep()

三、线程的interrupt

四、join()

五、yield()

六、wait(),notify(),notifyAll()


一、线程名称设置和获取

1、线程名称一般在线程启动前设置,但也允许为正在运行的线程设置名称。在实际开发中,在使用多线程开发时,一定要自定义线程名称,偏于查找日志。

2、线程允许使用同样的名字,但应该尽量避免。

3、如果线程没有命名,系统会自动为线程设置名称。例如Thread-0,Thread-1。在SpringBoot中http-nio-端口号-exec-1,http-nio-端口号-exec-2。

线程命名

package com.xiaojie.juc.thread.base;

/**
 * @author xiaojie
 * @version 1.0
 * @description: 线程命名和获取名称
 * @date 2021/12/17 22:54
 */
public class ThreadNameDemo {

    public static void main(String[] args) {
        A a = new A();
        new Thread(a,"mythraed-a").start();
        new Thread(a,"mythraed-b").start();
    }

    static class A implements Runnable{
        @Override
        public void run() {
            //获取线程名称
            System.out.println("当前线程的名称是>>>>>>>>:"+Thread.currentThread().getName());
        }
    }
}

线程池命名

package com.xiaojie.juc.thread.base;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author xiaojie
 * @version 1.0
 * @description: 线程池命名
 * @date 2021/12/17 23:09
 */
public class ThreadPoolNameDemo {
    private static final AtomicInteger threadNumber = new AtomicInteger(1);
    private static final String MYTHREAD_POOL_GROUP = "mythread-pool-group-thread-";

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3, 
                r -> new Thread(new ThreadGroup(""), r,
                MYTHREAD_POOL_GROUP + threadNumber.getAndIncrement(),
                0));
        for (int i = 0; i < 10; i++) {
            executorService.execute(() -> 
                    System.out.println("当前线程名称>>>>>>>>>:" + Thread.currentThread().getName()));
        }
        //关闭线程池
        executorService.shutdown();
    }
}

二、线程的sleep()

package com.xiaojie.juc.thread.base;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author xiaojie
 * @version 1.0
 * @description: 线程sleep方法
 * @date 2021/12/17 23:46
 */
public class ThreadSleepDemo {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            executorService.execute(() -> {
                try {
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("Thread is Interrupted");
                    }
                    //一定要捕捉InterruptedException异常
                    Thread.sleep(1000);
                } catch (InterruptedException e) {

                }
                System.out.println(Thread.currentThread().getName());
            });
        }
        //关闭线程池
        executorService.shutdown();
    }
}

sleep的作用是让目前正在执行的线程休眠,让CPU去执行其他任务,使线程从运行状态进去阻塞状态。当线程睡眠时间满后,线程并不一定是立刻马上开始执行,因为CPU可能正在执行其他任务,线程进入就绪状态,等待CPU分配时间片后才能执行。

三、线程的interrupt

Thread提供了stop(),但是是个过时方法,不推荐使用。stop()方法是强制中断线程,不管当前线程是否正在运行,有可能导致当前线程持有当前锁,强行中断后可能不会释放锁。interrupt()并不是用来中断一个线程,而是将线程设置为中断状态。

1、如果执行interrupt()时,当前线程处于阻塞状态(wait(),sleep(),join())时,线程会立刻退出阻塞,抛出InterruptedException异常。

2、如果调用interrupt()时,线程处于运行状态,线程不受任何影响,只是会将中断标识设置为true,可以调用isInterrupted(),判断是否中断。

package com.xiaojie.juc.thread.base;

/**
 * @author xiaojie
 * @version 1.0
 * @description: 线程中断
 * @date 2021/12/18 0:12
 */
public class InterruptDemo {

    public static void main(String[] args) {
        A a = new A();
        a.start();
    }

    static class A extends Thread {
        @Override
        public void run() {
            //手动中断线程
            Thread.currentThread().interrupt();
            try {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("线程中断了");
                        break;
                    }
                }
                Thread.sleep(3000);
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("线程中断了。。。。。when sleep");
            }
        }
    }
}

四、join()

JUC并发编程——线程的基本方法使用_第1张图片

 线程A在运行时,线程Bjoin(),之后,线程A会等待直到线程B运行完之后,才开始执行。如果线程B无限制运行,线程A可以设置等待时长join(1000)单位是毫秒。

package com.xiaojie.juc.thread.base;

/**
 * @author xiaojie
 * @version 1.0
 * @description:线程join模拟
 * @date 2021/12/18 0:45
 */
public class ThreadJoinDemo {

    public static void main(String[] args) {
        new A().start();
    }

    static class A extends Thread {
        @Override
        public void run() {
            try {
                B b = new B();
                b.start();
                b.join();//B线程join之后,A线程需要等待B运行完之后才执行

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程A执行任务。。。。。。。");
        }
    }

    static class B extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程B执行任务。。。。。。。");
        }
    }
}

五、yield()

yield的作用是让正在执行的线程让出CPU的执行权限,使得CPU可以去执行其他任务。从线程状态来看,线程从运行变为就绪状态。线程在yield()方法之后,线程放弃和重占CPU是不确定的,可能是刚刚放弃CPU,马上又获得CPU执行权。yield不会阻塞线程,只会让当前线程暂停一下,让系统线程调度器重新调度一次。

package com.xiaojie.juc.thread.base;

/**
 * @author xiaojie
 * @version 1.0
 * @description: Yield实例
 * @date 2021/12/18 1:13
 */
public class ThreadYieldDemo {
    public static void main(String[] args) {
        Thread threadA = new Thread(new A());
        threadA.setPriority(1);
        threadA.setName("threadA ");
        Thread threadB = new Thread(new B());
        threadB.setName("threadB ");
        threadA.start();
        threadB.start();
    }

    static class A implements Runnable {
        @Override
        public void run() {
            //暂停一下,重新调度线程
            Thread.yield();
            System.out.println(Thread.currentThread().getName());
        }
    }

    static class B implements Runnable {

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }
}

六、wait(),notify(),notifyAll()

这三个方法不是Thread独有的方法,是Object的方法!!!

当一个对象实例调用了wait()方法后,当前线程会在这个对象上等待。直到其他线程调用这个实例的notify(),或者notifyAll()方法后才会唤醒。调用了wait()方法后,该线程就会进入该实例的等待队列,如果队列中有多个线程,notify()只会随机的唤醒一个线程。这个选择是不公平的,不是先等待的就会先唤醒。notifyAll(),是唤醒所有的等待线程。而且这些方法只能在synchronized代码块中使用。wait()和sleep()都会让线程等待,但是wait()方法会释放目标对象的锁,而sleep()方法不会释放任何资源。

package com.xiaojie.juc.thread.base;

/**
 * @author xiaojie
 * @version 1.0
 * @description: wait demo
 * @date 2021/12/18 1:43
 */
public class ThreadWaitDemo {
    private static final Object obj = new Object();

    public static void main(String[] args) {
        new Thread(new A()).start();
        new Thread(new B()).start();
    }

    static class A implements Runnable {

        @Override
        public void run() {
            synchronized (obj) {
                System.out.println("线程A开始等待。。。。。。");
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程A等待结束。。。。。。");
                System.out.println("线程A开始执行。。。。。。");
            }
        }
    }

    static class B implements Runnable {

        @Override
        public void run() {
            synchronized (obj) {
                try {
                    obj.notify();
                    Thread.sleep(2000);
                    System.out.println("线程B运行。。。。。");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

参考:《JAVA高并发核心编程(卷2):多线程、锁、JMM、JUC、高并发设计》-尼恩编著

你可能感兴趣的:(JUC,JUC,多线程,并发编程)