创建线程的方式

继承Thread类

  1. class MyThread extends Thread {
  2. @Override
  3. public void run() {
  4. System.out.println("haha");
  5. }
  6. }

实现Runnable接口

  1. class MyThread implements Runnable {
  2. @Override
  3. public void run() {
  4. System.out.println("haha");
  5. }
  6. }

实现Callable接口

  1. public class MyCallable implements Callable<String> {
  2. @Override
  3. public String call() throws Exception {
  4. Thread.sleep(3000);
  5. return "Hello Callable";
  6. }
  7. }
  8. //普通调用
  9. public void testCallable() throws ExecutionException, InterruptedException {
  10. FutureTask<String> task = new FutureTask<String>(new MyCallable());
  11. new Thread(task).start();
  12. if (!task.isDone()) {
  13. System.out.println("Task is wait");
  14. }
  15. System.out.println(task.get());
  16. }
  17. //线程池调用
  18. public void testThreadPool() {
  19. ExecutorService es = Executors.newCachedThreadPool();
  20. Future<String> task = es.submit(new MyCallable());
  21. if (!task.isDone()) {
  22. System.out.println("task is wait");
  23. }
  24. try {
  25. System.out.println(task.get());
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. } catch (ExecutionException e) {
  29. e.printStackTrace();
  30. } finally {
  31. es.shutdown();
  32. }
  33. }

线程的状态

新建(NEW):创建后尚未启动的线程状态 运行(RUNNABLE):包含Ready和Running 阻塞(BLOCKED):等待获取排它锁。例如:等待锁进入synchronize块 等待(WAITING):不会被分配CPU执行时间,需要显示被唤醒。例如调用了Object.waitThread.joinLockSupport.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()方法判断当前方法是否被中断了