创建线程的方式
继承Thread类
class MyThread extends Thread {@Overridepublic void run() {System.out.println("haha");}}
实现Runnable接口
class MyThread implements Runnable {@Overridepublic void run() {System.out.println("haha");}}
实现Callable接口
public class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {Thread.sleep(3000);return "Hello Callable";}}//普通调用public void testCallable() throws ExecutionException, InterruptedException {FutureTask<String> task = new FutureTask<String>(new MyCallable());new Thread(task).start();if (!task.isDone()) {System.out.println("Task is wait");}System.out.println(task.get());}//线程池调用public void testThreadPool() {ExecutorService es = Executors.newCachedThreadPool();Future<String> task = es.submit(new MyCallable());if (!task.isDone()) {System.out.println("task is wait");}try {System.out.println(task.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();} finally {es.shutdown();}}
线程的状态
新建(NEW):创建后尚未启动的线程状态 运行(RUNNABLE):包含Ready和Running 阻塞(BLOCKED):等待获取排它锁。例如:等待锁进入synchronize块 等待(WAITING):不会被分配CPU执行时间,需要显示被唤醒。例如调用了
Object.wait,Thread.join,LockSupport.park就会一直等待除非被唤醒 限期等待(TIMED_WAITING):在一定时间后由系统自动唤醒。例如:Object.wait(10),Thread.join(10),LockSupport.parkNanos(10),LockSupport.parkUntil(10)终止状态(TERMINATED):线程执行完成
Sleep和Wait区别
Sleep和Wait方法都可以放线程让出CPU时间 Sleep是Thread类中的方法,但是Wait是Object类中的方法 Sleep仅让出CPU但不释放锁等资源,Wait会释放锁资源 Wait必须在
synchronize中执行
public void testSleepAndWait() throws InterruptedException {
final Object lock = new Object();
new Thread(() -> {
System.out.println("Enter Thread 1");
synchronized (lock) {
try {
System.out.println("Thread 1 got the lock");
Thread.sleep(20);
System.out.println("Thread 1 do wait method");
lock.wait(1000);
System.out.println("Thread 1 is done");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(1000);
new Thread(() -> {
System.out.println("Enter Thread 2");
synchronized (lock) {
try {
System.out.println("Thread 2 got the lock");
Thread.sleep(10);
System.out.println("Thread 2 is done");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(1000);
}
上述代码Thread1中如果使用wait方法会把lock释放,而Thread1如果不使用wait方法的话就会导致线程2阻塞,一直等待线程1释放锁资源
notify和notifyAll
notify:从等待池中的线程中随机唤醒一个线程 notifyAll:将等待池中的所有线程唤醒 这两个方法都需要在
synchronize中执行
AllArgsConstructor
public class NotifyTest implements Runnable {
final Object lock;
@Override
public void run() {
System.out.println("Enter Thread " + Thread.currentThread().getName());
try {
synchronized (lock) {
lock.wait();
System.out.println(Thread.currentThread().getName() + " is done");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void testNotify() throws InterruptedException {
final Object lock = new Object();
NotifyTest notifyTest = new NotifyTest(lock);
Thread t1 = new Thread(notifyTest);
Thread t2 = new Thread(notifyTest);
Thread t3 = new Thread(notifyTest);
t1.start();
t2.start();
t3.start();
Thread.sleep(3000);
synchronized (lock) {
//lock.notify();
lock.notifyAll();
}
}
在测试方法中如果调用的是notify方法的话,那么在3个wait线程中只会被随机唤醒其中1个,其他2个线程会一直阻塞。而如果调用的是notifyAll方法的话就会唤醒所有在wait状态中的线程
yield方法
该方法表示让当前线程可以让出CPU时间,回到Runnable状态,但是并不一定真正让出CPU时间,具体还是要看操作系统调度
interrupt方法
如果线程处于被阻塞状态,那么线程将立即退出并抛出
InterruptedException如果线程处于活动状态,那么会讲该线程中断位设置为true。被设置中断的线程将继续正常运营,不受影响 可以通过Thread.interrupted()方法判断当前方法是否被中断了
