代码搬运自柏码知识库
线程创建于启动 Thread构造方法中需要传入一个Runnable接口的实现, 可以直接使用lambda表达式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @FunctionalInterface public interface Runnable { public abstract void run () ; }
1 2 3 4 5 6 7 8 9 10 11 public static void main (String[] args) throws InterruptedException { Thread t = new Thread (() -> { Thread me = Thread.currentThread(); for (int i = 0 ; i < 50 ; i++) { System.out.println("打印:" +i); if (i == 20 ) me.stop(); } Thread.sleep(1000 ); }); t.start(); }
虽然stop()方法能够终止此线程,但是并不是所推荐的做法。
线程休眠与中断 使用interrupt()方法来发送中断标记来中断进程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static void main (String[] args) { Thread t = new Thread (() -> { System.out.println("线程开始运行!" ); while (true ){ if (Thread.currentThread().isInterrupted()){ break ; } } System.out.println("线程被中断了!" ); }); t.start(); try { Thread.sleep(3000 ); t.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); } }
使用Thread.interrupted()复位,清除中断标记。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public static void main (String[] args) { Thread t = new Thread (() -> { System.out.println("线程开始运行!" ); while (true ){ if (Thread.currentThread().isInterrupted()){ System.out.println("发现中断信号,复位,继续运行..." ); Thread.interrupted(); } } }); t.start(); try { Thread.sleep(3000 ); t.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); } }
优先级 包括三种优先级:
MIN_PRIORITY 最低优先级
MAX_PRIORITY 最高优先级
NOM_PRIORITY 常规优先级
1 2 3 4 5 6 7 public static void main (String[] args) { Thread t = new Thread (() -> { System.out.println("线程开始运行!" ); }); t.start(); t.setPriority(Thread.MIN_PRIORITY); }
礼让与加入 使用yield()方法与join()方法。
线程锁与线程同步 通过synchronized关键字来创造一个线程锁。两个线程必须使用同一把锁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 private static int value = 0 ;public static void main (String[] args) throws InterruptedException { Thread t1 = new Thread (() -> { for (int i = 0 ; i < 10000 ; i++) { synchronized (Main.class){ value++; } } System.out.println("线程1完成" ); }); Thread t2 = new Thread (() -> { for (int i = 0 ; i < 10000 ; i++) { synchronized (Main.class){ value++; } } System.out.println("线程2完成" ); }); t1.start(); t2.start(); Thread.sleep(1000 ); System.out.println(value); }
synchronized关键字也可以作用于方法上,调用此方法时也会获取锁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 private static int value = 0 ;private static synchronized void add () { value++; }public static void main (String[] args) throws InterruptedException { Thread t1 = new Thread (() -> { for (int i = 0 ; i < 10000 ; i++) add(); System.out.println("线程1完成" ); }); Thread t2 = new Thread (() -> { for (int i = 0 ; i < 10000 ; i++) add(); System.out.println("线程2完成" ); }); t1.start(); t2.start(); Thread.sleep(1000 ); System.out.println(value); }
死锁 使用jps与jstack可以检测死锁。
不推荐使用 suspend()去挂起线程的原因,是因为suspend()在使线程暂停的同时,并不会去释放任何锁资源。其他线程都无法访问被它占用的锁。直到对应的线程执行resume()方法后,被挂起的线程才能继续,从而其它被阻塞在这个锁的线程才可以继续执行。但是,如果resume()操作出现在suspend()之前执行,那么线程将一直处于挂起状态,同时一直占用锁,这就产生了死锁。
wait与notify wait暂停并释放锁。notify随机唤起一个暂停的线程。notifyAll唤起所有。两个方法使用锁来调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public static void main (String[] args) throws InterruptedException { Object o1 = new Object (); Thread t1 = new Thread (() -> { synchronized (o1){ try { System.out.println("开始等待" ); o1.wait(); System.out.println("等待结束!" ); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread t2 = new Thread (() -> { synchronized (o1){ System.out.println("开始唤醒!" ); o1.notify(); for (int i = 0 ; i < 50 ; i++) { System.out.println(i); } } }); t1.start(); Thread.sleep(1000 ); t2.start(); }
ThreadLocal 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public static void main (String[] args) throws InterruptedException { ThreadLocal<String> local = new ThreadLocal <>(); Thread t1 = new Thread (() -> { local.set("lbwnb" ); System.out.println("线程1变量值已设定!" ); try { Thread.sleep(2000 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程1读取变量值:" ); System.out.println(local.get()); }); Thread t2 = new Thread (() -> { local.set("yyds" ); System.out.println("线程2变量值已设定!" ); }); t1.start(); Thread.sleep(1000 ); t2.start(); }
在InheritableThreadLocal存放的内容,会自动向子线程传递。
1 2 3 4 5 6 7 8 9 10 public static void main (String[] args) { ThreadLocal<String> local = new InheritableThreadLocal <>(); Thread t = new Thread (() -> { local.set("lbwnb" ); new Thread (() -> { System.out.println(local.get()); }).start(); }); t.start(); }
定时器 1 2 3 4 5 6 7 8 9 10 public static void main (String[] args) { Timer timer = new Timer (); timer.schedule(new TimerTask () { @Override public void run () { System.out.println(Thread.currentThread().getName()); timer.cancel(); } }, 1000 ); }