创建后尚未启动。
可能正在运行,也可能正在等待 CPU 时间片。
包含了操作系统线程状态中的 Running 和 Ready。
等待获取一个排它锁,如果其他线程释放了锁就会结束此状态
等待其它线程显式地唤醒,否则不会被分配 CPU 时间片
进入等待方法 | 退出等待方法 |
---|---|
Object.wait() | Object.nofity或Object.nofityAll |
Thread.join() | 被调用的线程执行完毕 |
LockSupport.park()方法 |
阻塞是等待其他线程施放锁,是被动的,等待是线程主动的行为
进入等待方法 | 退出等待方法 |
---|---|
Object.wait(timeout) | Object.notify或Object.notifyAll |
Thread.join(millis) | 时间结束或者被调用的线程执行完 |
LockSupport.parkNanos() | |
LockSuppert.parkUntil() |
线程执行完毕或因产生异常而结束
实现Runnable和Callable接口最后还是需要通过Thread来调用
实现runnable接口,重写run方法
class RunTask implements Runnable{
@Override
public void run() {
System.out.println("你好");
}
}
public static void main(String[] args){
RunTask runTask = new RunTask();
Thread thread = new Thread(runTask);
thread.start();
}
Callable接口可以有返回值,通过FuTureTask封装
class RunTask implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("你好");
Thread.sleep(2000);
return "ok ok";
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
RunTask runTask = new RunTask();
FutureTask<String> futureTask = new FutureTask<>(runTask);
Thread thread = new Thread(futureTask);
thread.start();
System.out.println(futureTask.get());
}
继承了Thread类后,还需要重写run方法
class RunTask extends Thread {
@Override
public void run(){
System.out.println("111");
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
RunTask runTask = new RunTask();
runTask.start();
}
守护线程在主线程结束时,自己也会结束
通过Thread的setDeamon实现
class RunTask implements Runnable {
@Override
public void run(){
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("111");
}
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
RunTask runTask = new RunTask();
Thread thread = new Thread(runTask);
thread.setDaemon(true);
thread.start();
Thread.sleep(2000);
System.out.println("主线程结束");
}
调用interrupt()方法来中断线程,如果线程处于阻塞、限期等待或者无限期等待,就会抛出InterruptException,从而提前结束线程,但是不能中断IO阻塞和synchronized锁阻塞
class RunTask implements Runnable {
@Override
public void run(){
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("111");
}
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
RunTask runTask = new RunTask();
Thread thread = new Thread(runTask);
thread.setDaemon(true);
thread.start();
thread.interrupt();
}
代码执行就会报错 java.lang.InterruptedException: sleep interrupted
该方法可以判断当前线程是否被中断,可以在线程中调用这个方法,然后再主线程中调用interrupt()来中断线程
class RunTask extends Thread {
@Override
public void run(){
while(!interrupted()){
System.out.println("111");
}
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
RunTask runTask = new RunTask();
Thread thread = new Thread(runTask);
thread.setDaemon(true);
thread.start();
Thread.sleep(1000);
thread.interrupt();
}
Executors.shutdown()会等线程执行结束之后再关闭,但是如果调用shutdownNow()就会调用每个线程的interrupt()方法
在ThreadPoolExecotor中,shutdownNow方法回调用一个interruptWorkers方法,在该方法中,回去循环中断每个线程
public void func(){
synchronized (this){
}
}
作用域同一个对象,如果调用两个对象上的同步代码块,就不会同步
定义一个同步代码块如下
class RunTask{
public void func(){
synchronized (this){
for(int i=0;i<10;i++){
System.out.println(i);
}
}
}
}
在main方法中创建他的对象示例,并在线程池中运行
public class Info{
public static void main(String[] args) throws ExecutionException, InterruptedException {
RunTask rt = new RunTask();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> rt.func());
executorService.execute(() -> rt.func());
}
}
此时输出结果为0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9,可见两个线程存在同步关系
然后我们在建立两个示例对象在执行线程池
public static void main(String[] args) throws ExecutionException, InterruptedException {
RunTask rt = new RunTask();
RunTask rt1 = new RunTask();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> rt.func());
executorService.execute(() -> rt1.func());
}
此时输出结果为0 1 2 3 4 5 6 7 0 1 2 3 4 5 8 9 6 7 8 9,可见此时线程未同步
作用跟synchronized同步代码块一致
public synchronized void func(){
// todo
}
作用于整个类,若两个线程调用同一个类的不同对象实例,也会进行同步操作
class RunTask{
public void func(){
synchronized (RunTask.class){
for(int i=0;i<10;i++){
System.out.print(i+" ");
}
}
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
RunTask rt = new RunTask();
RunTask rt1 = new RunTask();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> rt.func());
executorService.execute(() -> rt1.func());
}
输出结果为0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
与作用于类一致
public synchronized static void func(){
// todo
}
ReenTrantLock是java.lang.concurrent中的锁
class RunTask{
private ReentrantLock lock = new ReentrantLock();
public void func(){
try{
lock.lock();
for(int i=0;i<10;i++){
System.out.print(i+" ");
}
}finally {
lock.unlock();
}
}
}
public class Info{
public static void main(String[] args) throws ExecutionException, InterruptedException {
RunTask rt = new RunTask();
RunTask rt1 = new RunTask();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> rt.func());
executorService.execute(() -> rt1.func());
}
}
输出结果0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
在一个线程中调用另一个线程的join方法,会把当前线程挂起,直到目标线程结束
wait() 使得线程等待某个条件满足,线程在等待时会被挂起,使用 wait() 挂起期间,线程会释放锁,其它线程会调用 notify() 或者 notifyAll() 来唤醒挂起的线程。
class WaitNotifyExample {
static final Object lock = new Object();
public synchronized void before() {
synchronized(lock){
System.out.println("before");
try {
Thread.sleep(1500);
lock.notifyAll();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public void after() {
synchronized(lock){
try {
lock.wait();
System.out.println("after");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
ExecutorService executorService = Executors.newCachedThreadPool();
WaitNotifyExample example = new WaitNotifyExample();
executorService.execute(() -> example.after());
executorService.execute(() -> example.before());
executorService.shutdown();
执行结果为before after
java.utin.concurrent.Condition可以通过await使线程等待,其他线程调用signal和signalAll唤醒线程,await可以指定等待的条件
class AWaitSignalExample {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void before() {
lock.lock();
try{
System.out.println("before");
condition.signal();
}finally {
lock.unlock();
}
}
public void after() {
lock.lock();
try {
condition.await();
System.out.println("after");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
AWaitSignalExample example = new AWaitSignalExample();
executorService.execute(() -> example.after());
executorService.execute(() -> example.before());
executorService.shutdown();
}
运行结果before after