线程工厂类生成线程
public class MyThreadFactory implements ThreadFactory {
private int counter;
private String name;
private List<String> stats;
public MyThreadFactory(String name){
counter=0;
this.name=name;
stats=new ArrayList<>();
}
@Override
public Thread newThread(Runnable r) {
Thread t=new Thread(r,name+"-Thread_"+counter);
counter++;
stats.add(String.format("Created thread %d with name %s on %s\n",t.getId(),t.getName(),new Date()));
return t;
}
public String getStats(){
StringBuffer buffer=new StringBuffer();
Iterator<String> it=stats.iterator();
while (it.hasNext()) {
buffer.append(it.next());
buffer.append("\n");
}
return buffer.toString();
}
public static void main(String[] args) {
MyThreadFactory factory=new MyThreadFactory("MyThreadFactory");
Task task=new Task();
Thread thread;
System.out.printf("Starting the Threads\n");
for (int i=0; i<10; i++){
thread=factory.newThread(task);
thread.start();
}
System.out.printf("Factory stats:\n");
System.out.printf("%s\n",factory.getStats());
}
}
class Task implements Runnable {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized
public class Account {
private double balance;
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public synchronized void addAmount(double amount) {
double tmp=balance;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
tmp+=amount;
balance=tmp;
}
public synchronized void subtractAmount(double amount) {
double tmp=balance;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
tmp-=amount;
balance=tmp;
}
public static void main(String[] args) {
Account account=new Account();
account.setBalance(1000);
Company company=new Company(account);
Thread companyThread=new Thread(company);
Bank bank=new Bank(account);
Thread bankThread=new Thread(bank);
System.out.printf("Account : Initial Balance: %f\n",account.getBalance());
companyThread.start();
bankThread.start();
try {
companyThread.join();
bankThread.join();
System.out.printf("Account : Final Balance: %f\n",account.getBalance());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Bank implements Runnable {
private Account account;
public Bank(Account account) {
this.account=account;
}
@Override
public void run() {
for (int i=0; i<100; i++){
account.subtractAmount(1000);
}
}
}
class Company implements Runnable {
private Account account;
public Company(Account account) {
this.account=account;
}
@Override
public void run() {
for (int i=0; i<100; i++){
account.addAmount(1000);
}
}
}
运行正确synchronized 粒度越小越好
synchronized类中管理两个独立的变量
public class Cinema {
private long vacanciesCinema1;
private long vacanciesCinema2;
private final Object controlCinema1, controlCinema2;
public Cinema(){
controlCinema1=new Object();
controlCinema2=new Object();
vacanciesCinema1=20;
vacanciesCinema2=20;
}
public boolean sellTickets1 (int number) {
synchronized (controlCinema1) {
if (number<vacanciesCinema1) {
vacanciesCinema1-=number;
return true;
} else {
return false;
}
}
}
public boolean sellTickets2 (int number){
synchronized (controlCinema2) {
if (number<vacanciesCinema2) {
vacanciesCinema2-=number;
return true;
} else {
return false;
}
}
}
public boolean returnTickets1 (int number) {
synchronized (controlCinema1) {
vacanciesCinema1+=number;
return true;
}
}
public boolean returnTickets2 (int number) {
synchronized (controlCinema2) {
vacanciesCinema2+=number;
return true;
}
}
public long getVacanciesCinema1() {
return vacanciesCinema1;
}
public long getVacanciesCinema2() {
return vacanciesCinema2;
}
public static void main(String[] args) {
Cinema cinema=new Cinema();
TicketOffice1 ticketOffice1=new TicketOffice1(cinema);
Thread thread1=new Thread(ticketOffice1,"TicketOffice1");
TicketOffice2 ticketOffice2=new TicketOffice2(cinema);
Thread thread2=new Thread(ticketOffice2,"TicketOffice2");
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Room 1 Vacancies: %d\n",cinema.getVacanciesCinema1());
System.out.printf("Room 2 Vacancies: %d\n",cinema.getVacanciesCinema2());
}
}
class TicketOffice1 implements Runnable {
private Cinema cinema;
public TicketOffice1 (Cinema cinema) {
this.cinema=cinema;
}
@Override
public void run() {
cinema.sellTickets1(3);
cinema.sellTickets1(2);
cinema.sellTickets2(2);
cinema.returnTickets1(3);
cinema.sellTickets1(5);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
}
}
class TicketOffice2 implements Runnable {
private Cinema cinema;
public TicketOffice2(Cinema cinema){
this.cinema=cinema;
}
@Override
public void run() {
cinema.sellTickets2(2);
cinema.sellTickets2(4);
cinema.sellTickets1(2);
cinema.sellTickets1(1);
cinema.returnTickets2(2);
cinema.sellTickets1(3);
cinema.sellTickets2(2);
cinema.sellTickets1(2);
}
}
执行正常
同步代码中生产者消费者.
public class EventStorage {
private int maxSize;
private LinkedList<Date> storage;
public EventStorage(){
maxSize=10;
storage=new LinkedList<>();
}
public synchronized void set(){
while (storage.size()==maxSize){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
storage.offer(new Date());
System.out.printf("Set: %d",storage.size());
notifyAll();
}
public synchronized void get(){
while (storage.size()==0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Get: %d: %s",storage.size(),((LinkedList<?>)storage).poll());
notifyAll();
}
public static void main(String[] args) {
EventStorage storage=new EventStorage();
Producer producer=new Producer(storage);
Thread thread1=new Thread(producer);
Consumer consumer=new Consumer(storage);
Thread thread2=new Thread(consumer);
thread2.start();
thread1.start();
}
}
class Producer implements Runnable {
private EventStorage storage;
public Producer(EventStorage storage){
this.storage=storage;
}
@Override
public void run() {
for (int i=0; i<100; i++){
storage.set();
}
}
}
class Consumer implements Runnable {
private EventStorage storage;
public Consumer(EventStorage storage){
this.storage=storage;
}
@Override
public void run() {
for (int i=0; i<100; i++){
storage.get();
}
}
}
调用wait方法当前线程暂停释放锁,调用notifyAll方法唤醒释放锁的线程。notify唤醒沉睡的线程后,线程会接着上次的执行继续往下执行。所以在进行条件判断时候,可以先把 wait 语句忽略不计来进行考虑;显然,要确保程序一定要执行,并且要保证程序直到满足一定的条件再执行,要使用while进行等待,直到满足条件才继续往下执行。存储一定不会超过10个数据
notify方法只唤醒一个等待(对象的)线程并使该线程开始执行。所以如果有多个线程等待一个对象,这个方法只会唤醒其中一个线程,选择哪个线程取决于操作系统对多线程管理的实现。notifyAll 会唤醒所有等待(对象的)线程,尽管哪一个线程将会第一个处理取决于操作系统的实现。如果当前情况下有多个线程需要被唤醒,推荐使用notifyAll 方法。比如在生产者-消费者里面的使用,每次都需要唤醒所有的消费者或是生产者,以判断程序是否可以继续往下执行。
notify 和wait 的顺序不能错,如果A线程先执行notify方法,B线程在执行wait方法,那么B线程是无法被唤醒的。
wait() 需要被try catch包围,以便发生异常中断也可以使wait等待的线程唤醒。
用Lock实现同步,比synchronized 更好
public class PrintQueue {
private final Lock queueLock=new ReentrantLock();
public void printJob(Object document){
queueLock.lock();
try {
Long duration=(long)(Math.random()*10000);
System.out.println(Thread.currentThread().getName()+ ": PrintQueue: Printing a Job during "+(duration/1000)+
" seconds");
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
queueLock.unlock();
}
}
public static void main (String args[]){
PrintQueue printQueue=new PrintQueue();
Thread thread[]=new Thread[10];
for (int i=0; i<10; i++){
thread[i]=new Thread(new Job(printQueue),"Thread "+ i);
}
for (int i=0; i<10; i++){
thread[i].start();
}
}
}
class Job implements Runnable {
private PrintQueue printQueue;
public Job(PrintQueue printQueue){
this.printQueue=printQueue;
}
@Override
public void run() {
System.out.printf("%s: Going to print a document\n", Thread.currentThread().getName());
printQueue.printJob(new Object());
System.out.printf("%s: The document has been printed\n", Thread.currentThread().getName());
}
}
读写锁
public class PricesInfo {
private double price1;
private double price2;
private ReadWriteLock lock;
public PricesInfo(){
price1=1.0;
price2=2.0;
lock=new ReentrantReadWriteLock();
}
public double getPrice1() {
lock.readLock().lock();
double value=price1;
lock.readLock().unlock();
return value;
}
public double getPrice2() {
lock.readLock().lock();
double value=price2;
lock.readLock().unlock();
return value;
}
public void setPrices(double price1, double price2) {
lock.writeLock().lock();
this.price1=price1;
this.price2=price2;
lock.writeLock().unlock();
}
public static void main(String[] args) {
PricesInfo pricesInfo=new PricesInfo();
Reader readers[]=new Reader[5];
Thread threadsReader[]=new Thread[5];
for (int i=0; i<5; i++){
readers[i]=new Reader(pricesInfo);
threadsReader[i]=new Thread(readers[i]);
}
Writer writer=new Writer(pricesInfo);
Thread threadWriter=new Thread(writer);
for (int i=0; i<5; i++){
threadsReader[i].start();
}
threadWriter.start();
}
}
class Reader implements Runnable {
private PricesInfo pricesInfo;
public Reader (PricesInfo pricesInfo){
this.pricesInfo=pricesInfo;
}
@Override
public void run() {
for (int i=0; i<10; i++){
System.out.printf("%s: Price 1: %f\n", Thread.currentThread().getName(),pricesInfo.getPrice1());
System.out.printf("%s: Price 2: %f\n", Thread.currentThread().getName(),pricesInfo.getPrice2());
}
}
}
class Writer implements Runnable {
private PricesInfo pricesInfo;
public Writer(PricesInfo pricesInfo){
this.pricesInfo=pricesInfo;
}
@Override
public void run() {
for (int i=0; i<3; i++) {
System.out.printf("Writer: Attempt to modify the prices.\n");
pricesInfo.setPrices(Math.random()*10, Math.random()*8);
System.out.printf("Writer: Prices have been modified.\n");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
公平锁-等待时间最长的线程最先执行,ReentrantLock 和ReentrantReadWriteLock 都有这种参数
Lock中的conditions实现生产者消费者
public class FileMock {
private String content[];
private int index;
public FileMock(int size, int length){
content=new String[size];
for (int i=0; i<size; i++){
StringBuilder buffer=new StringBuilder(length);
for (int j=0; j<length; j++){
int indice=(int)Math.random()*255;
buffer.append((char)indice);
}
content[i]=buffer.toString();
}
index=0;
}
public boolean hasMoreLines(){
return index<content.length;
}
public String getLine(){
if (this.hasMoreLines()) {
System.out.println("Mock: "+(content.length-index));
return content[index++];
}
return null;
}
public static void main(String[] args) {
FileMock mock=new FileMock(100, 10);
Buffer buffer=new Buffer(20);
Producer producer=new Producer(mock, buffer);
Thread threadProducer=new Thread(producer,"Producer");
Consumer consumers[]=new Consumer[3];
Thread threadConsumers[]=new Thread[3];
for (int i=0; i<3; i++){
consumers[i]=new Consumer(buffer);
threadConsumers[i]=new Thread(consumers[i],"Consumer "+i);
}
threadProducer.start();
for (int i=0; i<3; i++){
threadConsumers[i].start();
}
}
}
class Buffer {
private LinkedList<String> buffer;
private int maxSize;
private ReentrantLock lock;
private Condition lines;
private Condition space;
private boolean pendingLines;
public Buffer(int maxSize) {
this.maxSize=maxSize;
buffer=new LinkedList<>();
lock=new ReentrantLock();
lines=lock.newCondition();
space=lock.newCondition();
pendingLines=true;
}
public void insert(String line) {
lock.lock();
try {
while (buffer.size() == maxSize) {
space.await();
}
buffer.offer(line);
System.out.printf("%s: Inserted Line: %d\n", Thread.currentThread().getName(),buffer.size());
lines.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public String get() {
String line=null;
lock.lock();
try {
while ((buffer.size() == 0) &&(hasPendingLines())) {
lines.await();
}
if (hasPendingLines()) {
line = buffer.poll();
System.out.printf("%s: Line Readed: %d\n",Thread.currentThread().getName(),buffer.size());
space.signalAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return line;
}
public void setPendingLines(boolean pendingLines) {
this.pendingLines=pendingLines;
}
public boolean hasPendingLines() {
return pendingLines || buffer.size()>0;
}
}
class Producer implements Runnable {
private FileMock mock;
private Buffer buffer;
public Producer (FileMock mock, Buffer buffer){
this.mock=mock;
this.buffer=buffer;
}
@Override
public void run() {
buffer.setPendingLines(true);
while (mock.hasMoreLines()){
String line=mock.getLine();
buffer.insert(line);
}
buffer.setPendingLines(false);
}
}
class Consumer implements Runnable {
private Buffer buffer;
public Consumer (Buffer buffer) {
this.buffer=buffer;
}
@Override
public void run() {
while (buffer.hasPendingLines()) {
String line=buffer.get();
processLine(line);
}
}
private void processLine(String line) {
try {
Random random=new Random();
Thread.sleep(random.nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Condition 接口还有其他版本的await() 方法,如下:
await(long time, TimeUnit unit):这个线程会睡眠直到:
1.他被中断
2.另外一个线程调用 singal() or signalAll() 方法
3.指定的时间到达
awaitUninterruptibly(): 这个线程会睡眠直到其他线程调用 singal() or signalAll() 方法,不能被中断。
awaitUntil(Date date):这个线程会睡眠直到:
1.他被中断
2.另外一个线程调用 singal() or signalAll() 方法
3.指定的日期到达
调用await()方法后如果处理不当可能会永远睡眠下去
read/write lock类也有Condition 方法