# Java拾遗-并发-Thread
一个个小例子深入了解知识点
代码地址
# 1. Thread
/**
* 线程的创建方式一 - 继承Thread
* 线程的创建方式二 - 实现Runnable
* 线程的创建方式三 - JDK8直接创建
*
* 请你告诉我启动线程的三种方式 1:Thread 2: Runnable 3:Executors.newCachedThrad
*
* @author wliduo[i@dolyw.com]
* @date 2020/4/14 10:20
*/
public class T01_Thread {
private static class CreateThread1 extends Thread {
@Override
public void run() {
// CreateThread1线程循环打印
for (int i = 0; i < 50; i++) {
try {
// 休眠1S,不然无法时时切换线程
TimeUnit.MICROSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("CreateThread1");
}
}
}
private static class CreateThread2 implements Runnable {
@Override
public void run() {
// CreateThread2线程循环打印
for (int i = 50; i < 100; i++) {
try {
// 休眠1S,不然无法时时切换线程
TimeUnit.MICROSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("CreateThread2");
}
}
}
public static void main(String[] args) {
// 线程的创建方式一 - 继承Thread
CreateThread1 createThread1 = new CreateThread1();
// 启动线程
createThread1.start();
// 线程的创建方式二 - 实现Runnable
Thread createThread2 = new Thread(new CreateThread2());
// 启动线程
createThread2.start();
// 线程的创建方式三 - JDK8直接创建
new Thread(() -> {
for (int i = 0; i < 50; i++) {
try {
// 休眠1S,不然无法时时切换线程
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("CreateThread3");
}
}).start();
// 主线程循环打印
for (int i = 50; i < 100; i++) {
try {
// 休眠1S,不然无法时时切换线程
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main");
}
}
/**
* JAVA中让当前线程睡眠一段时间的方式
* 方法一:通过线程的sleep方法
* Thread.sleep(1000);
* Thread.currentThread().sleep(1000);
* 上面两种没区别,参数1000是以毫秒为单位,即这语句可以让程序等待1秒
* 方法二:TimeUnit类里的sleep方法
* java.util.concurrent.TimeUnit;这个类里封装着
* TimeUnit.DAYS.sleep(1); //天
* TimeUnit.HOURS.sleep(1); //小时
* TimeUnit.MINUTES.sleep(1); //分
* TimeUnit.SECONDS.sleep(1); //秒
* TimeUnit.MILLISECONDS.sleep(1000); //毫秒
* TimeUnit.MICROSECONDS.sleep(1000); //微妙
* TimeUnit.NANOSECONDS.sleep(1000); //纳秒
* TimeUnit类提供的方法,底层调用的也是Thread类的sleep方法,只是在上层根据时间单位进行封装
*/
}
# 2. yield
/**
* 了解一下就行 - 线程的休眠方式 - Thread.yield()
* Thread.yield()与Thread.sleep(1000)或者TimeUnit.MILLISECONDS.sleep(1000)区别
* 主要是前两者都是存在指定休眠时间,时间到了才能继续执行,而Thread.yield()只是让步
* 就是当前线程让出当前时间片给其他线程执行,继续回到等待队列,也可能可能再次被选中执行
*
* yield()方法会通知线程调度器放弃对处理器的占用,但调度器可以忽视这个通知。
* yield()方法主要是为了保障线程间调度的连续性,防止某个线程一直长时间占用cpu资源。
* 但是他的使用应该基于详细的分析和测试。
* 这个方法一般不推荐使用,它主要用于debug和测试程序,用来减少bug以及对于并发程序结构的设计
*
* @author wliduo[i@dolyw.com]
* @date 2020/4/14 10:20
*/
public class T02_yield {
private static class CreateThread implements Runnable {
@Override
public void run() {
// CreateThread线程循环打印
for (int i = 0; i < 50; i++) {
System.out.println("CreateThread3");
}
}
}
public static void main(String[] args) {
Thread thread = new Thread(new CreateThread());
// 启动线程
thread.start();
// 写法
Thread.yield();
// 主线程循环打印
for (int i = 0; i < 50; i++) {
System.out.println("Main3");
}
}
/**
* JAVA中可以通过让当前线程睡眠一段时间的方式
* 方法一:通过线程的sleep方法
* Thread.sleep(1000);
* Thread.currentThread().sleep(1000);
* 上面两种没区别,参数1000是以毫秒为单位,即这语句可以让程序等待1秒
* 方法二:TimeUnit类里的sleep方法
* java.util.concurrent.TimeUnit;这个类里封装着
* TimeUnit.DAYS.sleep(1); //天
* TimeUnit.HOURS.sleep(1); //小时
* TimeUnit.MINUTES.sleep(1); //分
* TimeUnit.SECONDS.sleep(1); //秒
* TimeUnit.MILLISECONDS.sleep(1000); //毫秒
* TimeUnit.MICROSECONDS.sleep(1000); //微妙
* TimeUnit.NANOSECONDS.sleep(1000); //纳秒
* TimeUnit类提供的方法,底层调用的也是Thread类的sleep方法,只是在上层根据时间单位进行封装
*/
}
# 3. join
/**
* 线程的方法 - join()
* 调用某线程的某方法,将当前线程和该线程合并,等待该线程结束,再恢复当前线程的允许
*
* createThread1.join();
* createThread2.join();
* 主线程调用join(),线程1,2交替执行
*
* 如果完全按顺序执行,主线程调用线程2的join(),线程2内run方法第一行调用线程1的join()
*
* 当我们在join()方法中传入参数时,比如1000,那么主线程只会阻塞1000ms,然后就恢复了并行的执行状态
* 简单说就是只会等待子线程执行1000ms
*
* @author wliduo[i@dolyw.com]
* @date 2020/4/14 10:20
*/
public class T03_join {
public static void main(String[] args) {
// 创建线程一
Thread createThread1 = new Thread(() -> {
// CreateThread1线程循环打印
for (int i = 0; i < 10; i++) {
try {
// 休眠1S,不然无法时时切换线程
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("CreateThread1");
}
});
// 创建线程二
Thread createThread2 = new Thread(() -> {
try {
// 线程二里调用线程一的join()
createThread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// CreateThread2线程循环打印
for (int i = 20; i < 30; i++) {
try {
// 休眠1S,不然无法时时切换线程
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("CreateThread2");
}
});
// 启动线程
createThread1.start();
createThread2.start();
/*try {
// 主线程调用join(),线程1,2交替执行
createThread1.join();
createThread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}*/
try {
// 如果完全按顺序执行,主线程调用线程2的join(),线程2内run方法第一行调用线程1的join()
// createThread2.join();
// 当我们在join()方法中传入参数时,比如1000,那么主线程只会阻塞1000ms,然后就恢复了并行的执行状态
// createThread2.join(1000);
// 参数区别第一个是毫秒,第二个是纳秒,等待时间就是毫秒+纳秒,时间更精确
createThread2.join(1000, 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 主线程循环打印
for (int i = 1; i < 10; i++) {
try {
// 休眠1S,不然无法时时切换线程
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main");
}
}
}
# 4. State
/**
* 线程的状态 - getState() - State枚举
*
* NEW,新建状态,尚未启动的线程的线程状态
*
* RUNNABLE,可运行线程的线程状态,可运行程序中的线程,
* 状态正在Java虚拟机中执行,但它可能正在等待来自操作系统的其他资源,例如处理器
*
* BLOCKED,等待监视器锁定时被阻止的线程的线程状态,
* 处于阻塞状态的线程正在等待监视器锁定输入同步块/方法或调用后重新输入同步的块/方法 Object.wait()
*
* WAITING,等待线程的线程状态,由于调用以下方法 Object.wait()没有超时 Thread.join()没有超时 LockSupport.park()
* 处于等待状态的线程正在等待另一个线程执行特定的动作
*
* TIMED_WAITING,具有指定等待时间的等待线程的线程状态,由于调用具有指定正等待时间的以下方法
* Thread.sleep() Object.wait() Thread.join() LockSupport.parknos() LockSupport.parkUntil()
*
* TERMINATED,终止线程的线程状态,线程已完成执行
*
* @author wliduo[i@dolyw.com]
* @date 2020/4/14 10:20
*/
public class T04_State {
public static void main(String[] args) {
// 创建线程
Thread thread = new Thread(() -> {
System.out.println("-----" + Thread.currentThread().getState());
// 线程循环打印
for (int i = 0; i < 5; i++) {
try {
// 休眠1ms,不然无法时时切换线程
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----" + Thread.currentThread().getState());
System.out.println("Thread");
}
System.out.println("-----" + Thread.currentThread().getState());
}, "diy-thread");
System.out.println("-----" + thread.getState().name());
// 启动线程
thread.start();
System.out.println("-----" + thread.getState().name());
// 主线程循环打印
for (int i = 10; i < 15; i++) {
try {
// 休眠1ms,不然无法时时切换线程
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main");
}
try {
// 先执行完thread线程
thread.join();
System.out.println("-----" + thread.getState());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----" + thread.getState());
}
}
← Java Java拾遗-Lock →