生产者消费者.java
import java.util.concurrent.LinkedBlockingQueue;
public class LocalTest {
public static void main(String[] args) {
LinkedBlockingQueue<Object> list = new LinkedBlockingQueue<Object>();
Storage store = new Storage(list);
Producer p1 = new Producer(store);
Producer p2 = new Producer(store);
Producer p3 = new Producer(store);
Producer p4 = new Producer(store);
Producer p5 = new Producer(store);
Producer p6 = new Producer(store);
Producer p7 = new Producer(store);
Producer p8 = new Producer(store);
Producer p9 = new Producer(store);
Producer p10 = new Producer(store);
Producer p11 = new Producer(store);
Consumer c1 = new Consumer(store);
Consumer c2 = new Consumer(store);
Consumer c3 = new Consumer(store);
Consumer c4 = new Consumer(store);
Consumer c5 = new Consumer(store);
Consumer c6 = new Consumer(store);
Consumer c7 = new Consumer(store);
Consumer c8 = new Consumer(store);
p1.start();
p2.start();
c2.start();
p3.start();
c1.start();
p4.start();
c3.start();
p5.start();
p6.start();
c4.start();
p7.start();
p8.start();
p9.start();
c5.start();
c6.start();
p10.start();
p11.start();
c7.start();
c8.start();
}
}
import java.util.concurrent.LinkedBlockingQueue;
public class Storage {
private LinkedBlockingQueue<Object> list;
public Storage(LinkedBlockingQueue<Object> list) {
this.list = list;
}
public LinkedBlockingQueue<Object> getList() {
return list;
}
}
import java.util.concurrent.LinkedBlockingQueue;
public class Producer extends Thread {
private Storage str;
public Producer(Storage str) {
this.str = str;
}
public void run() {
LinkedBlockingQueue<Object> list = str.getList();
if (list.size() == 100) {
System.out.println(Thread.currentThread().getName() + "-" + "仓库已满!");
}
for (int i=1; i<Math.random()*20; i++) {
try {
list.put(new Object());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "-" + "库存:" + list.size());
}
}
import java.util.concurrent.LinkedBlockingQueue;
public class Consumer extends Thread {
private Storage str;
public Consumer(Storage str) {
this.str = str;
}
public void run() {
LinkedBlockingQueue<Object> list = str.getList();
if (list.size() == 100) {
System.out.println(Thread.currentThread().getName() + "-" + "仓库已满!");
}
for (int i=1; i<5; i++) {
try {
list.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "-" + "库存:" + list.size());
}
}
同步方法.java
/**
* 同步方法: 有 synchronized 关键字修饰的方法, 当方法调用 synchronized 关键字声明的时候,
* Java 内置锁会保护整个方法, 即在调用该方法之前, 需要获得内置锁, 否则就会处于阻塞状态.
* 注意: synchronized 关键字亦可以修饰静态方法, 如若调用此方法将会锁住整个类!!!
*/
线程局部变量.java
/**
* Java 提供了很多种方式和工具类来帮助程序员简化多线程的开发, 同步方法是最简单和最常用的的一种!!!
* 使用 ThreadLocal 类管理线程的局部变量, 使每个线程都能获得相互独立的副本, 每个线程都可以随意的修改自己的变量值而不会对其他线程产生任何影响.
*/
public class Bank {
private static ThreadLocal<Integer> account = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 100;
}
};
public void deposit(int money) {
account.set(account.get() + money);
}
public int getAccount() {
return account.get();
}
}
public class Transfer implements Runnable {
private Bank bank;
public Transfer(Bank bank) {
this.bank = bank;
}
public void run() {
for (int i = 0; i < 10; i++) {
bank.deposit(10);
System.out.println("账户余额是: " + bank.getAccount());
}
}
}
信号量.java
/**
* 信号量是由 Dijkstra 在 1968 年发明的, 该概念最初是用于在进程间发信号的一个整数值.
* 一个信号量有且仅有 3 种操作, 且全部是原子的: 1.初始化, 2.增加, 3.减少
* 增加可以为一个进程解除阻塞;
* 减少可以让一个进程进入阻塞;
*
* Java 的 Semaphore 类是一个计数信号量, 从概念上讲, 信号量维护了一个许可集, 如有必要. 在许可可用之前会阻塞每一个
* acquire(), 然后再获取该许可, 每个 release() 添加一个许可, 从而可能释放一个正在阻塞的获取者. 但是, 不使用实际的
* 许可对象, Semaphore 只对可用许可的号码进行计数, 并采取相应的行动. 声明如下:
* public Semaphore(int permits, boolean fair) 参数说明:
* permits: 初始的可用许可数目, 该值可能为负数, 在这种情况下, 必须在授予任何获取前进行释放.
* fair: 如果该信号量保证在争用时按先进先出的授权许可, 则为 true, 反之为 false.
* 1.为了从信号量获得一个许可, 需要使用 acquire() 方法, 声明如下:
* public void acquire() throws InterruptedException
* 2.为了释放一个许可到的信号量, 需要使用 release() 方法, 声明如下:
* public void release()
*/
public class Bank {
private int account = 100;
public void deposit(int money) {
account += money;
}
public int getAccount() {
return account;
}
}
public class Transfer implements Runnable {
private Bank bank;
private Semaphore semaphore;
public Transfer(Bank bank, Semaphore semaphore) {
this.bank = bank;
this.semaphore = semaphore;
}
public void run() {
for (int i = 0; i < 10; i++) {
try {
semaphore.acquire();
bank.deposit(10);
System.out.println("账户的余额是: " + bank.getAccount());
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
原子变量.java
/**
* 需要使用线程同步的根本原因在于对普通变量的操作并不是原子的! 所谓原子操作是将读取变量值、修改变量值、保存变量值看作一个整体,要么同时完成,要么不同时完成,参考数据库的事务原理。
*/
public class Bank {
private AtomicInteger account = new AtomicInteger(100);
public void deposit(int money) {
account.addAndGet(money);
}
public int getAccount() {
return account.get();
}
}
public class Transfer implements Runnable {
private Bank bank;
public Transfer(Bank bank) {
this.bank = bank;
}
public void run() {
for ( int i = 0; i < 10; i++ ) {
bank.deposit(10);
System.out.println("账户的余额是: " + bank.getAccount());
}
}
}
哲学家就餐.java
/**
* 死锁: 哲学家就餐问题!
*
* 布尔变量: true 表示吃饭! false 表示思考!
*/
private boolean state;
public synchronized void eating() {
if (!state) {
if (chopstickArray.getRight(id).isAvailable()) {
if (chopstickArray.getLeft(id).isAvailable()) {
chopstickArray.getRight(id).setAvailable(false);
chopstickArray.getleft(id).setAvailable(false);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
wait(new Random().nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
try {
wait(new Random().nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
state = true;
}
重入锁.java
/**
* ReentrantLock 类是可重入、互斥实现了 Lock 接口的锁, 具有和使用 Synchronized 方法相同的基本行为和语义, 并且大大扩展了其能力.
*/
public class Bank {
private int account = 100;
private Lock lock = new ReentrantLock();
public void deposit(int money) {
lock.lock();
try {
account += money;
} finally {
lock.unlock();
}
}
public int getAccount() {
return account;
}
}
public class Transfer implements Runnable {
private Bank bank;
public Transfer(Bank bank) {
this.bank = bank;
}
public void run() {
for (int i = 0; i < 10; i++) {
bank.deposit(10);
System.out.println("账户余额是: " + bank.getAccount());
}
}
}
阻塞队列.java
/**
* 多线程基础实例介绍了如何在底层实现线程同步, 但在实际开发中应尽量远离底层结构, 使用 java.util.concurrent 包将有助于简化开发.
*/
public class Producer implements Runnable {
public void run() {
for (int i = 0; i<size; i++) {
int b = new Random().nextInt(255);
System.out.println("生产商品: " + b);
try {
queue.put(b);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("仓库中还有" + queue.size() + "个商品");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}