J2SE多线程

原创 2012年03月24日 13:44:50
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;
		}
	}
	
}




J2SE知识点归纳笔记(五)---Java多线程(一)

Java多线程: 前言: 当我们使用电脑时,可以一边听歌,一边和小学生打lol,一边用QQ和基友聊天;如果你够屌的话,还可以 用wps做实验报告呢= =;那么CPU怎么同时敢这么...

【转载】J2SE知识点归纳笔记(五)---Java多线程(二)

注:本文转载自coder-pig 原文请戳:http://blog.csdn.net/coder_pig/article/details/23182329 最近这些文章都比较基础,...

J2SE之多线程

J2SE之多线程1、多线程基础 1、线程与进程 进程:一个正在执行的程序 线程:进程中负责程序执行的执行单元。一个进程中至少有一个线程 一个进程至...

【转载】 J2SE知识点归纳笔记(五)---Java多线程(一)

注:本文转载自coder-pig 原文请戳:http://blog.csdn.net/coder_pig/article/details/22791141 一口吃不成一个胖子,所以...

J2SE学习笔记:多线程、单例模式延迟加载懒汉式同步、死锁问题

package cn.itcast.threaddemo; /** * 开启新线程两种方式: * 1.继承Thread类。在主线程中new 一个Thread子类对象,调用start()。 * 2...

【J2SE】java多线程学习笔记

Runnable接口的使用: //执行 New Thread(runnable class).start() 执行 runnable calss的run方法。 publicclass hello im...

J2SE快速进阶——Java多线程机制

学习Java中的线程时,自然而然地联想到之前学过的操作系统中处理器那一块的知识。    定义        文章开头,先大概说一下程序、进程和线程的概念及其之间的关系。        程序:程序就...

04、J2SE基础-多线程

多线程 了解进程和线程: 在多任务系统中,每个独立执行的程序称为进程, 一个进程中又可以包含一个或多个线程,一个线程就是程序内部的一条执行线索 用Thread类创建线程 1、要将...
  • DBAFAN
  • DBAFAN
  • 2012年03月04日 15:56
  • 281

马士兵J2SE-第九章-多线程机制-sleep、join、yield、线程优先级

sleep: package com.zzk.test; import java.util.*; public class Test{ public static void main...

马士兵J2SE-第九章-多线程机制-线程的创建与启动

public class test{ public static void main(String[] args) { m1(); } public static void m...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:J2SE多线程
举报原因:
原因补充:

(最多只允许输入30个字)