package thread; //使用锁对象、条件对象 import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class SynchBankTest { public static final int NACCOUNTS = 100; public static final double INITIAL_BALANCE = 1000; public static void main(String[] args) { Bank b = new Bank(NACCOUNTS, INITIAL_BALANCE); for (int i=0; i<NACCOUNTS; i++) { Runnable r = new TransferRunnable(b,i,INITIAL_BALANCE); Thread t = new Thread(r); t.start(); } } } class Bank { private final double[] accounts; private Lock bankLock; //每个Bank对象都有自己的ReentrantLock对象 private Condition sufficientFunds; public Bank(int n, double initialBalance) { accounts = new double[n]; for(int i=0; i<accounts.length; i++) { accounts[i] = initialBalance; } bankLock = new ReentrantLock(); sufficientFunds = bankLock.newCondition();//一个锁对象可以有一个或多个相关联的条件对象 } public void transfer(int from, int to, double amount) throws InterruptedException { bankLock.lock(); try { while (accounts[from] < amount) sufficientFunds.await();//当前线程被阻塞了,并且放弃了锁 System.out.print(Thread.currentThread()); accounts[from] -= amount; System.out.printf(" %10.2f from %d to %d", amount,from,to); accounts[to] += amount; //调用getTotalBalance时会重复持有锁,持有计数+1,当持有数为0时,线程把锁释放 System.out.printf(" Total Balance: %10.2f%n", this.getTotalBalance()); sufficientFunds.signalAll();//解除所有等待此条件的线程的阻塞状态,从等待池移出,成为可运行 }finally { bankLock.unlock(); } } public double getTotalBalance() { bankLock.lock(); try { double sum = 0; for(double a : accounts) { sum += a; } return sum; } finally { bankLock.unlock(); } } public int size() { return accounts.length; } } class TransferRunnable implements Runnable { private Bank bank; private int fromCount; private double maxAmount; private int DELAY = 10; public TransferRunnable() { } public TransferRunnable(Bank b,int fromCount,double maxAmount) { this.bank = b; this.fromCount = fromCount; this.maxAmount = maxAmount; } public void run() { try { while(true){ int toCount = (int)(bank.size() * Math.random()); double amount = maxAmount * Math.random(); bank.transfer(fromCount, toCount, amount); Thread.sleep((int)(DELAY * Math.random())); } }catch(InterruptedException e) {} } }
package thread; //使用阻塞队列 import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Scanner; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class BlockingQueueTest { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("Enter base directory:"); String directory = in.nextLine(); System.out.print("Enter keyword:"); String keyword = in.nextLine(); final int FILE_QUEUE_SIZE = 102; final int SEARCH_THREADS = 100; BlockingQueue<File> queue = new ArrayBlockingQueue<File>(FILE_QUEUE_SIZE); FileEnumerationTask enumerator = new FileEnumerationTask(queue,new File(directory)); new Thread(enumerator).start(); for(int i=0; i< SEARCH_THREADS; i++) { new Thread(new SearchTask(queue,keyword)).start(); } } } //生产者线程用来枚举制定目录及子目录下的所有文件,放入阻塞队列中 class FileEnumerationTask implements Runnable { private BlockingQueue<File> queue; private File statingDirectory; public static File DUMMY = new File("");//一个虚拟的对象,用来发出完成信号 public FileEnumerationTask(BlockingQueue<File> queue, File statingDirectory) { this.queue = queue; this.statingDirectory = statingDirectory; } public void run() { try { enumerate(statingDirectory); queue.put(DUMMY); } catch(InterruptedException e) {} } public void enumerate(File directory) throws InterruptedException { File[] files = directory.listFiles(); for(File f : files) { if (f.isDirectory()) enumerate(f); else queue.put(f);//如果队列已满,则阻塞,可能抛出InterruptedException } } } //大量搜索线程各自从阻塞队列中取出一个文件,对文件内容进行搜索 class SearchTask implements Runnable { private BlockingQueue<File> queue; private String keyword; public SearchTask(BlockingQueue<File> queue, String keyword) { this.queue = queue; this.keyword = keyword; } public void run() { try { boolean done = false; while(!done) { File f = queue.take();//队列为空时,阻塞,可能抛出InterruptedException if(f == FileEnumerationTask.DUMMY){queue.put(f); done = true;} search(f); } }catch (IOException e) { e.printStackTrace(); }catch (InterruptedException e) { } } public void search(File f) throws IOException { Scanner in = new Scanner(new FileInputStream(f)); int lineNumber = 0; while(in.hasNextLine()) { lineNumber ++; String line = in.nextLine(); if(line.contains(keyword)) { System.out.printf("%s:%d:%n",f.getPath(),lineNumber,line); } } in.close(); } }
package thread; // Callable 和 Future //计算给出路径下与关键字匹配的文件数量 import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; public class FutureTest { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("Enter base directory:"); String directory = in.nextLine(); System.out.print("Enter keyword:"); String keyword = in.nextLine(); MatchCounter counter = new MatchCounter(new File(directory),keyword); FutureTask<Integer> task = new FutureTask<Integer>(counter); Thread t = new Thread(task); t.start(); try { System.out.println(task.get()); } catch (InterruptedException e) { } catch (ExecutionException e) { e.printStackTrace(); } } } class MatchCounter implements Callable<Integer> { private File directory; private String keyword; private int count; public MatchCounter(File directory, String keyword) { this.directory = directory; this.keyword = keyword; } public Integer call(){//Callable<Integer>接口代表有一个最终返回Integer对象的异步计算 count = 0; try{ File[] files = directory.listFiles(); ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>(); for(File file : files) { if(file.isDirectory()) { MatchCounter counter = new MatchCounter(file,keyword); FutureTask<Integer> task = new FutureTask<Integer>(counter); results.add(task);//FutureTask包装器是一种将Callable转换成Future和Runnable的机制 Thread t = new Thread(task); t.start(); }else { if(search(file)) count ++; } } //Future用来保存异步计算的结果 for(Future<Integer> result : results) { count += result.get();//Future<Integer>中get()调用会被阻塞,直至计算完成 } }catch(Exception e) { e.printStackTrace(); } return count; } public boolean search(File file) { try { Scanner in = new Scanner(new FileInputStream(file)); boolean found = false; while(!found && in.hasNextLine()) { String line = in.nextLine(); if(line.contains(keyword)) found = true; } in.close(); return found; }catch(IOException e) { return false; } } }
package thread; //用执行器构建线程池来完成任务 import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; public class ThreadPoolTest { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("Enter base directory:"); String directory = in.nextLine(); System.out.print("Enter keyword:"); String keyword = in.nextLine(); //Executors执行器类有大量构建线程池的静态工厂方法, //newCachedThreadPool()在需要时创建新线程,空闲线程会被保留60秒 ExecutorService pool = Executors.newCachedThreadPool(); MatchCounter1 counter = new MatchCounter1(new File(directory), keyword, pool); //将Runnable或Callable对象提交给ExecutorService,池在方便的时候会在第一时间运行提交上来的任务, //返回Future对象可以用来查询任务的状态 Future<Integer> result = pool.submit(counter); try { System.out.println(result.get()+"matching files"); } catch (InterruptedException e) { } catch (ExecutionException e) { } pool.shutdown();//启动池的关闭序列,被关闭的执行器不再接受新的任务 int largestPoolSize = ((ThreadPoolExecutor)pool).getLargestPoolSize(); System.out.println("largest pool size = "+ largestPoolSize); } } class MatchCounter1 implements Callable<Integer> { private File directory; private String keyword; private ExecutorService pool; private int count; public MatchCounter1(File directory, String keyword,ExecutorService pool) { this.directory = directory; this.keyword = keyword; this.pool = pool; } public Integer call() { count = 0; try { File[] files = directory.listFiles(); ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>(); for(File file : files) { if(file.isDirectory()) { MatchCounter1 counter = new MatchCounter1(file,keyword,pool); Future<Integer> result = pool.submit(counter); results.add(result); }else { if (search(file)) count ++; } } for(Future<Integer> result : results) { try { count += result.get();//Future<Integer>中get()调用会被阻塞,直至计算完成 } catch (ExecutionException e) {} } }catch(InterruptedException e) {} return count; } public boolean search(File file) { try { Scanner in = new Scanner(new FileInputStream(file)); boolean found = false; while(!found && in.hasNextLine()) { String line = in.nextLine(); if(line.contains(keyword)) found = true; } in.close(); return found; }catch(IOException e) { return false; } } }