多线程实现
方法1: 继承Thread
类
public class Main { public static void main(String[] args) throws InterruptedException { Worker worker1 = new Worker(); worker1.setName("thread-worker1"); Worker worker2 = new Worker(); worker2.setName("thread_worker2"); worker1.start(); worker2.start(); Thread.sleep(1000); System.out.println("Main-thread finished!"); } } class Worker extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("Hello " + getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } |
方法2: 实现Runnable
接口
public class Main { public static void main(String[] args) { Worker worker = new Worker("thread1"); new Thread(worker).start(); new Thread(worker).start(); } } class Worker implements Runnable{ private String name; public Worker(String name) { this.name = name; } @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("Hello " + this.name); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } |
join(long millis)
: 等待该线程执行结束,父线程才会继续执行; 可以传入一个最长等待时间,超过该时间后继续执行父线程
例如:主线程要等worker1
和worker2
进程结束后执行
package cc.bnblogs; public class Main { public static void main(String[] args) throws InterruptedException { Worker worker1 = new Worker(); worker1.setName("thread-worker1"); Worker worker2 = new Worker(); worker2.setName("thread_worker2"); worker1.start(); worker2.start(); worker1.join(); // 只有worker1执行完成之后才会执行后面的代码 worker2.join(); // 只有worker2执行完成之后才会执行后面的代码 System.out.println("Main-thread finished!"); } } class Worker extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("Hello " + getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } |
interrupt()
:从休眠中中断线程
public class Main { public static void main(String[] args) throws InterruptedException { Worker worker1 = new Worker(); worker1.setName("thread-worker1"); Worker worker2 = new Worker(); worker2.setName("thread_worker2"); worker1.start(); worker2.start(); // 主线程最多等待worker1线程5000ms worker1.join(5000); worker1.interrupt(); // 抛出InterruptedException异常 System.out.println("Main-thread finished!"); } } class Worker extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("Hello " + getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { // 收到InterruptedException后,结束该线程 System.out.println(getName() + " stop!"); break; } } } } |
setDaemon()
:设置某线程为守护线程
public class Main { public static void main(String[] args) throws InterruptedException { Worker worker1 = new Worker(); worker1.setName("thread-worker1"); Worker worker2 = new Worker(); worker2.setName("thread_worker2"); // 将worker1和worker2设置为守护线程 // 除守护线程之外的其他线程结束后(这里只有主线程),守护线程会自动结束 worker1.setDaemon(true); worker2.setDaemon(true); worker1.start(); worker2.start(); // 主线程休眠5s Thread.sleep(5000); System.out.println("Main-thread finished!"); } } class Worker extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("Hello " + getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(); } } } } |
锁
lock
:获取锁,如果锁已经被其他线程获取,则阻塞 unlock
:释放锁,并唤醒被该锁阻塞的其他线程
防止读写冲突,同一时间只有一个线程可以拥有锁,并进行写操作
import java.util.concurrent.locks.ReentrantLock; public class Main { public static void main(String[] args) throws InterruptedException { Worker worker1 = new Worker(); worker1.setName("thread-worker1"); Worker worker2 = new Worker(); worker2.setName("thread_worker2"); worker1.start(); worker2.start(); worker1.join(); worker2.join(); System.out.println("Main-thread finished!"); System.out.println("cnt: " + Worker.cnt); } } class Worker extends Thread { private static final ReentrantLock lock = new ReentrantLock(); public static int cnt = 0; @Override public void run() { for (int i = 0; i < 200000; i++) { lock.lock(); try { cnt++; }finally { lock.unlock(); } } } } |
同步(Synchronized)
java实现锁的语法糖,继承Thread
类和实现Runnable
接口的线程使用方式有点区别
还是上面的cnt++
的例子
1.继承Thread
类
public class Main { public static void main(String[] args) throws InterruptedException { Worker worker1 = new Worker(); worker1.setName("thread-worker1"); Worker worker2 = new Worker(); worker2.setName("thread_worker2"); worker1.start(); worker2.start(); worker1.join(); worker2.join(); System.out.println("Main-thread finished!"); System.out.println("cnt: " + Worker.cnt); } } class Worker extends Thread { public static int cnt = 0; private static final Object object = new Object(); @Override public void run() { //锁加到了object对象上,多个线程共享一个object synchronized (object) { for (int i = 0; i < 200000; i++) { cnt++; } } } } |
2.实现Runnable
接口
public class Main { public static void main(String[] args) throws InterruptedException { Worker worker = new Worker(); Thread worker1 = new Thread(worker); Thread worker2 = new Thread(worker); worker1.start(); worker2.start(); worker1.join(); worker2.join(); System.out.println("Main-thread finished!"); System.out.println("cnt: " + Worker.cnt); } } class Worker implements Runnable { public static int cnt = 0; @Override public void run() { //锁加到了this对象上,而两个线程是由同一个worker创建而来的 synchronized (this) { for (int i = 0; i < 200000; i++) { cnt++; } } } } |
也可以直接将synchronized
作用到方法上,和上面的代码等价
public class Main { public static void main(String[] args) throws InterruptedException { Worker worker = new Worker(); Thread worker1 = new Thread(worker); Thread worker2 = new Thread(worker); worker1.start(); worker2.start(); worker1.join(); worker2.join(); System.out.println("Main-thread finished!"); System.out.println("cnt: " + Worker.cnt); } } class Worker implements Runnable { public static int cnt = 0; @Override public void run() { Worker.work(); } private synchronized static void work() { for (int i = 0; i < 200000; i++) { cnt++; } } } |
wait与notify
前面5个线程会等待1s后自动唤醒一个线程,唤醒的线程睡眠1s后叫醒下一个线程
public class Main { public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 5; i++) { Worker worker = new Worker(true); worker.setName("Thread_" + i); worker.start(); } Worker worker = new Worker(false); worker.setName("Thread_5"); // 第6个线程先睡2s再去唤醒线程,这时候已经晚了 Thread.sleep(2000); worker.start(); } } class Worker extends Thread { private final boolean needWait; // 定义一个全局object private static final Object object = new Object(); public Worker(boolean needWait) { this.needWait = needWait; } @Override public void run() { synchronized (object) { try { if (needWait) { // 最多等待1s,超过1s会自动唤醒一个线程 object.wait(1000); System.out.println(getName() + " 被唤醒了!"); //睡眠1s后继续唤醒其他线程 Thread.sleep(1000); } else { // 不需要睡眠的线程唤醒一个线程 object.notify(); System.out.println("尝试唤醒其他线程"); } } catch (InterruptedException e) { throw new RuntimeException(e); } } } } |
当然也可以不使用静态变量object
public class Main { public static void main(String[] args) throws InterruptedException { Object object = new Object(); for (int i = 0; i < 5; i++) { Worker worker = new Worker(object, true); worker.setName("Thread_" + i); worker.start(); } Worker worker = new Worker(object, false); worker.setName("Thread_5"); // 第6个线程先睡2s再去唤醒线程,这时候已经晚了 Thread.sleep(2000); worker.start(); } } class Worker extends Thread { private final boolean needWait; private final Object object; public Worker(Object object, boolean needWait) { this.object = object; this.needWait = needWait; } @Override public void run() { synchronized (object) { try { if (needWait) { // 最多等待1s,超过1s会自动唤醒一个线程 object.wait(1000); System.out.println(getName() + " 被唤醒了!"); //睡眠1s后继续唤醒其他线程 Thread.sleep(1000); } else { // 不需要睡眠的线程唤醒一个线程 object.notify(); System.out.println("尝试唤醒其他线程"); } } catch (InterruptedException e) { throw new RuntimeException(e); } } } } |