1、自定义线程基础类`
package com.yang.Threads;
public class ThreadDemo2 implements Runnable{
@Override
public void run() {
System.out.println("thread2 running....");
}
}
package com.yang.Threads;
import java.util.concurrent.Callable;
public class ThreadDemo implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("thread3 running...");
return "success";
}
}
package com.yang.Threads;
public class ThreadDemo1 extends Thread{
@Override
public void run() {
System.out.println("thread1 running.....");
}
}
2、实践线程的创建方式以及状态切换Test类
package com.yang.ThreadTest;
import com.yang.Threads.ThreadDemo;
import com.yang.Threads.ThreadDemo1;
import com.yang.Threads.ThreadDemo2;
import org.junit.jupiter.api.Test;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
public class Test1 {
// 测试线程的五种启动方式
@Test
public void fuction1() throws ExecutionException, InterruptedException {
//1 继承Thread类,重写run方法
new ThreadDemo1().start();
//2 实现Runnable接口
new Thread(new ThreadDemo2()).start();
//3 实现Callable接口,借助FutureTask接收返回值
FutureTask<String> stringFutureTask = new FutureTask<>(new ThreadDemo());
new Thread(stringFutureTask).start();
String s = stringFutureTask.get();
System.out.println(s);
//4 直接调用Thread类的run方法,lamda写法
new Thread(()->{
System.out.println("hello");
}).start();
//5 使用线程池启动线程
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10 ; i++) {
final int index = i;
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("thread--"+index);
}
});
}
for (int i = 0; i < 10; i++) {
final int num = i;
executorService.submit(stringFutureTask);
System.out.println(stringFutureTask.get());
}
}
// 测试线程的状态切换NEW > RUNNABLE > TERMINATED
@Test
public void function2() throws Exception{
Thread t1 = new Thread(() -> {
System.out.println("running.........");
System.out.println(Thread.currentThread().getName() +"........"+ Thread.currentThread().getState());
for (int i = 0; i < 3 ; i++) {
// 模拟线程t1的执行时间是3秒
try {
// Thread.sleep(1000);
// TimeUnit是java.util.concurrent包下的一个类名,主要功能是暂停线程的操作,与Thread.sleep()一样的功能都是暂停线程,入参有差异而已
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
});
t1.setName("Thread-1");
System.out.println(t1.getName()+"......."+t1.getState());
t1.start();
// System.out.println(t1.getState());
// 谁调用join方法,谁就强占cpu资源,直至执行结束,此处是t1
t1.join();
System.out.println(t1.getName()+"......."+t1.getState());
//-----------------------------------------------------------------------------------
Thread t2 = new Thread(()->{
// 让t2等待,阻塞住
LockSupport.park();
System.out.println("t2被唤醒继续执行,进入sleep");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t2.setName("Thread-2");
t2.start();
//主线程睡1秒
TimeUnit.SECONDS.sleep(1);
System.out.println(t2.getName()+"......"+t2.getState());
//唤醒t2
LockSupport.unpark(t2);
TimeUnit.SECONDS.sleep(1);
System.out.println(t2.getName()+"......"+t2.getState());
//------------------------------------------------------------------------------------
final Object o = new Object();
Thread t3 = new Thread(()->{
// 使用synchronized关键字的锁,等待锁的线程状态是BLOCKED
synchronized (o){
System.out.println("t3线程得到了锁 o");
}
});
t3.setName("Thread-3");
Thread t4 = new Thread(()->{
synchronized (o){
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t4.start();
TimeUnit.SECONDS.sleep(1);
t3.start();
TimeUnit.SECONDS.sleep(1);
System.out.println(t3.getName() + "......" + t3.getState());
t4.join();
//------------------------------------------------------------------------------
// 使用JUC包下的锁,等待锁的线程状态是WAITING
final Lock lock = new ReentrantLock();
Thread t5 = new Thread(()->{
lock.lock();
System.out.println("t5得到了锁");
lock.unlock();
});
t5.setName("Thread-5");
Thread t6 = new Thread(()->{
lock.lock();
try {
TimeUnit.SECONDS.sleep(5);
lock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t6.start();
TimeUnit.SECONDS.sleep(1);
t5.start();
TimeUnit.SECONDS.sleep(1);
System.out.println(t5.getName() + "......" + t5.getState());
t6.join();
//-----------------------------------------------------------------------------
//使用juc下的阻塞方法,等待的线程状态是WAITING
Thread t7 = new Thread(()->{
LockSupport.park();
});
t7.setName("Thread-7");
t7.start();
TimeUnit.SECONDS.sleep(1);
System.out.println(t7.getName() + "......" + t7.getState());
LockSupport.unpark(t7);
}
}
3、实践结果日志
Thread-1.......NEW
running.........
Thread-1........RUNNABLE
0
1
2
Thread-1.......TERMINATED
Thread-2......WAITING
t2被唤醒继续执行,进入sleep
Thread-2......TIMED_WAITING
Thread-3......BLOCKED
t3线程得到了锁 o
Thread-5......WAITING
t5得到了锁
Thread-7......WAITING
4、实践结论:只有使用synchronized关键字,等待锁的线程状态是BLOCKED;而使用JUC包下的锁(CAS)或者阻塞方法,阻塞的线程状态是WAITING或者TIMED_WAITING。