上一篇文章的传送门:关于一些基础的Java问题的解答(四)
public class Test { public static void main(String[] args) { new MyThread().start(); } private static class MyThread extends Thread { @Override public void run() { System.out.println("run!"); } } }
public class Test { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { System.out.println("run!"); } }).start(); } }
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); service.execute(new Runnable() { @Override public void run() { System.out.println("Run!"); } }); } }
public class Test { private static int value = 0; public static void main(String[] args) { Test test = new Test(); // 创建两个线程 MyThread thread1 = test.new MyThread(); MyThread thread2 = test.new MyThread(); thread1.start(); thread2.start(); } /** * 为静态变量value加2 * @return */ public int next() { value++; Thread.yield(); // 加速问题的产生 value++; return value; } /** * 判断是否偶数 * @param num * @return boolean 是否偶数 */ public boolean isEven(int num) { return num % 2 == 0; } class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread() + " start!"); while(isEven(next())); System.out.println(Thread.currentThread() + " down!"); } } }
/** * 为静态变量value加2 * @return */ public synchronized int next() { value++; Thread.yield(); // 加速问题的产生 value++; return value; }
/** * 为静态变量value加2 * * @return */ public int next() { synchronized (this) { value++; Thread.yield(); // 加速问题的产生 value++; return value; } }
private static Lock lock = new ReentrantLock(); /** * 为静态变量value加2 * @return */ public int next() { lock.lock(); try { value++; Thread.yield(); // 加速问题的产生 value++; return value; } finally { lock.unlock(); } }一般而言,当我们使用synchronized时,需要写的代码量更少,因此通常只有我们在解决某些特殊问题时,才需要使用到Lock对象,比如尝试去获得锁:
/** * 为静态变量value加2 * @return */ public int next() { boolean getLock = lock.tryLock(); if (getLock) { try { value++; Thread.yield(); // 加速问题的产生 value++; return value; } finally { lock.unlock(); } } else { // do something else System.out.println(Thread.currentThread() + "say : I don't get the lock, QAQ"); return 0; } }除了ReentrantLock外,Lock类还有众多子类锁,在此不做深入讨论。值得注意的是,很明显,使用Lock通常会比使用synchronized高效许多,但我们并发编程时都应该从synchronized关键字入手,只有在性能调优时才替换为Lock对象这种做法。
public synchronized void f() {}; public void g() { synchronized (this) { } }另外,synchronized也可以用来锁定类的静态方法和其中的代码块,此时关键字就是为类(类的Class对象)加锁了,因此被称为类锁:
public class Test { public static synchronized void f() {}; public static void g() { synchronized (Test.class) { } } }
import java.util.LinkedList; import java.util.Queue; class MyQueue { Queue<Integer> q; int size; // 队列持有产品数 final int MAX_SIZE = 5; // 队列最大容量 public MyQueue() { q = new LinkedList<>(); size = 0; } /** * 生产产品 * * @param num * 产品号码 */ public synchronized void produce(int num) { // 容量不足时,等待消费者消费 try { while (size > MAX_SIZE) wait(); } catch (InterruptedException e) { } ; System.out.println("produce " + num); q.add(num); size++; // 提醒消费者消费 notifyAll(); } /** * 消费产品 */ public synchronized void comsume() { // 没有产品时,等待生产 try { while (size < 1) wait(); } catch (InterruptedException e) { } ; System.out.println("comsume " + q.poll()); size--; // 提醒生产者生产 notifyAll(); } } class Producer extends Thread { private MyQueue q; public Producer(MyQueue q) { this.q = q; } @Override public void run() { for (int i = 0; i < 10; i++) q.produce(i); } } class Consumer extends Thread { private MyQueue q; public Consumer(MyQueue q) { this.q = q; } @Override public void run() { for (int i = 0; i < 10; i++) q.comsume(); } } public class Test { public static void main(String[] args) { MyQueue q = new MyQueue(); Producer producer = new Producer(q); Consumer consumer = new Consumer(q); producer.start(); consumer.start(); } }
import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class MyQueue { Queue<Integer> q; int size; // 队列持有产品数 final int MAX_SIZE = 5; // 队列最大容量 private Lock lock; // 锁 private Condition condition; // 条件变量 public MyQueue() { q = new LinkedList<>(); size = 0; lock = new ReentrantLock(); condition = lock.newCondition(); } /** * 生产产品 * * @param num * 产品号码 */ public void produce(int num) { // 进入临界区上锁 lock.lock(); // 容量不足时,等待消费者消费 try { while (size > MAX_SIZE) condition.await(); } catch (InterruptedException e) { e.printStackTrace(); }; System.out.println("produce " + num); q.add(num); size++; // 提醒消费者消费 condition.signalAll(); // 退出临界区解锁 lock.unlock(); } /** * 消费产品 */ public void comsume() { // 上锁进入临界区 lock.lock(); // 没有产品时,等待生产 try { while (size < 1) condition.await(); } catch (InterruptedException e) { e.printStackTrace(); }; System.out.println("comsume " + q.poll()); size--; // 提醒生产者生产 condition.signalAll(); // 退出临界区解锁 lock.unlock(); } } class Producer extends Thread { private MyQueue q; public Producer(MyQueue q) { this.q = q; } @Override public void run() { for (int i = 0; i < 10; i++) q.produce(i); } } class Consumer extends Thread { private MyQueue q; public Consumer(MyQueue q) { this.q = q; } @Override public void run() { for (int i = 0; i < 10; i++) q.comsume(); } } public class Main { public static void main(String[] args) { MyQueue q = new MyQueue(); Producer producer = new Producer(q); Consumer consumer = new Consumer(q); producer.start(); consumer.start(); } }
import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; class MyQueue { BlockingQueue<Integer> q; // 阻塞队列 int size; // 队列持有产品数(此例无用) final int MAX_SIZE = 5; // 队列最大容量 public MyQueue() { q = new LinkedBlockingQueue<>(MAX_SIZE); } /** * 生产产品 * * @param num * 产品号码 */ public void produce(int num) { // 阻塞队列会自动阻塞,不需要处理 try { q.put(num); System.out.println("produce " + num); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 消费产品 */ public void comsume() { // 阻塞队列会自动阻塞,不需要处理 try { System.out.println("comsume " + q.take()); } catch (InterruptedException e) { e.printStackTrace(); } } } class Producer extends Thread { private MyQueue q; public Producer(MyQueue q) { this.q = q; } @Override public void run() { for (int i = 0; i < 10; i++) q.produce(i); } } class Consumer extends Thread { private MyQueue q; public Consumer(MyQueue q) { this.q = q; } @Override public void run() { for (int i = 0; i < 10; i++) q.comsume(); } } public class Main { public static void main(String[] args) { MyQueue q = new MyQueue(); Producer producer = new Producer(q); Consumer consumer = new Consumer(q); producer.start(); consumer.start(); } }第四种方法(PipedInputStream和PipedOutputStream):
import java.io.PipedInputStream; import java.io.PipedOutputStream; class MyQueue { int size; // 队列持有产品数(此例无用) final int MAX_SIZE = 5; // 队列最大容量 PipedInputStream pis; PipedOutputStream pos; public MyQueue() { // 初始化流 pis = new PipedInputStream(MAX_SIZE); pos = new PipedOutputStream(); // 管道流建立连接 try { pos.connect(pis); } catch (Exception e) { e.printStackTrace(); } } /** * 生产产品 * * @param num * 产品号码 */ public void produce(int num) { // 管道流会自动阻塞,不需要处理 try { // 输出写在前面,否则会有奇怪的事情发生~ System.out.println("produce " + num); pos.write(num); pos.flush(); } catch (Exception e) { e.printStackTrace(); } } /** * 消费产品 */ public void comsume() { // 管道流会自动阻塞,不需要处理 try { System.out.println("comsume " + pis.read()); } catch (Exception e) { e.printStackTrace(); } } @Override protected void finalize() throws Throwable { pis.close(); pos.close(); super.finalize(); } } class Producer extends Thread { private MyQueue q; public Producer(MyQueue q) { this.q = q; } @Override public void run() { for (int i = 0; i < 10; i++) q.produce(i); } } class Consumer extends Thread { private MyQueue q; public Consumer(MyQueue q) { this.q = q; } @Override public void run() { for (int i = 0; i < 10; i++) q.comsume(); } } public class Main { public static void main(String[] args) { MyQueue q = new MyQueue(); Producer producer = new Producer(q); Consumer consumer = new Consumer(q); producer.start(); consumer.start(); } }
import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; class Accessor implements Runnable { private final int id; // 线程id public Accessor(int id) { this.id = id; } @Override public void run() { while(!Thread.currentThread().isInterrupted()) { ThreadLocalVariableHolder.increment(); System.out.println(this); Thread.yield(); } } @Override public String toString() { return "#" + id + " : " + ThreadLocalVariableHolder.get(); } } public class ThreadLocalVariableHolder { private static ThreadLocal<Integer> value = new ThreadLocal<Integer>() { // 返回随机数作为初始值 protected Integer initialValue() { return new Random().nextInt(10000); } }; /** * 为当前线程的value值加一 */ public static void increment() { value.set(value.get() + 1); } /** * 返回当前线程存储的value值 * @return */ public static int get() { return value.get(); } public static void main(String[] args) throws InterruptedException { ExecutorService service = Executors.newCachedThreadPool(); // 开启5个线程 for (int i = 0; i < 5; i++) service.execute(new Accessor(i)); // 所有线程运行3秒 TimeUnit.SECONDS.sleep(1); // 关闭所有线程 service.shutdownNow(); } }