java5线程并发库

ThreadLocal的使用,,,实际上相当于维护了一个Map,其中以键值对的形式,存储了某一个数据被多个线程访问所对应的值。当然这个数据只能有 一份,可以是List。。可以是对象。。可以是javabean。。。其Map中每一个Entry保存进去的键就是当前线程,值就是这个线程所访问的那份 数据。。。。比方说在服务器端单独起一个独立线程来实现与某个客户端交互,,,其中交互过程里所有涉及到的公共模块所访问的都是一份数据,,所以顾名思义 被叫做线程范围内的数据共享。。。。。想象的到在javaEE中的应用是非常多的。。。。

package localTest;

//import java.util.HashMap;
//import java.util.Map;
import java.util.Random;

public class ThreadLocalTest {
	public static int data;
//	public static Map dataMap = new HashMap();
//	public static ThreadLocal dataLocal = new ThreadLocal();
	public static void main(String[] args) {
		for (int i = 0; i < 2; i++) {
			new Thread() {
				public void run() {
//					ThreadLocalTest.data = new Random().nextInt();
//					ThreadLocalTest.dataMap.put(Thread.currentThread().getName(),
//							new Random().nextInt());
//					ThreadLocalTest.dataLocal.set(new Random().nextInt());
					int data = new Random().nextInt();
					MyData.getInstance().setData(data);
					System.out.println(Thread.currentThread().getName()
							+ " put data : " + data);
					System.out.println(Thread.currentThread().getName()
							+" A get data : " + new A().get());
					System.out.println(Thread.currentThread().getName()
							+" B get data : " + new B().get());
				}
			}.start();
		}
	}

}

class A {
	public int get() {
//		return (Integer)ThreadLocalTest.dataLocal.get();
		return MyData.getInstance().getData();
	}
}

class B {
	public int get() {
//		return (Integer)ThreadLocalTest.dataLocal.get();
		return MyData.getInstance().getData();
	}
}

class MyData{
	private static ThreadLocal<MyData> myData = new ThreadLocal<MyData>();
	private int data;
	public int getData(){
		return data;
	}
	public void setData(int data){
		this.data = data;
	}
	private MyData(){}
	public static MyData getInstance(){
		MyData data = myData.get();
		if(data==null){
			data = new MyData();
			myData.set(data);
		}
		return data;
	}
}
 

接着是线程并发库中的java.util.concurrent.atomic 包中提供了对一些数据类型的扩展,使得对那些数据类型的操作封装成为了方法,而那些方法都是线程安全的,atomic解释是原子的,,支持在单个变量上解除锁的线程安全编程。。。。其中包括Integer,boolean以及IntegerArray和引用类型。。

 

 

接下来就是线程池了,,于jdbc数据库连接池同理,,大大的提高了程序运行的效率。。因为创建一个新的线程还是很耗资源的。。

我们也只需要用到一个类,,java.util.concurrent包的老大,,,Executors类,,提供一系列静态方法,用于创建各种线 程池,,其中包含固定大小线程,和自动大小线程池(通过任务数量来分配线程数量),以及单一线程池(始终保持有一个线程在池子里)。。。还有可调度的线程 池,相当于定时器。。其中定时器任务代码内还可嵌套另外的定时器。。。通过调用线程池的shutdown方法在任务执行完毕后杀死池内线程。 shutdownNow直接杀死。。interrupt!ALL!!!

package concurrent;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolTest {
	public static void main(String[] args) {
		ExecutorService pool = Executors.newCachedThreadPool();//Executors.newFixedThreadPool(3);
		for (int i = 0; i < 10; i++) {
			final int taskId = i;
			pool.execute(new Runnable() {
				public void run() {
					for (int j = 0; j < 10; j++) {
						try {
							Thread.sleep(new Random().nextInt(1000));
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						System.out.println(Thread.currentThread().getName()
								+ " execute task " + taskId + 
								" loop for " + j);
					}
				}
			});
		}
		pool.shutdown();
	}
}





package concurrent;

import java.util.Calendar;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class TimerTaskTest {
	private static int count;
	public static void main(String[] args) {
		System.out.println(Calendar.getInstance().get(Calendar.SECOND));
		final ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		class MyTask implements Runnable{
			public void run(){
				count++;
				System.out.println(Calendar.getInstance().get(Calendar.SECOND));
				System.out.println("bombing!");
				if(count%2==1)
					timer.schedule(new MyTask(), 4, TimeUnit.SECONDS);
				else
					timer.schedule(new MyTask(), 3, TimeUnit.SECONDS);
			}
		}
		timer.schedule(new MyTask(), 2, TimeUnit.SECONDS);
	}
}

 Callable让线程能够拥有返回值,类似于Runnable接口,,需要实现call方法,,Future类接受一个Callable的返回值。。。 通过get方法获取返回值,当没有数据时,它将会等待,什么时候有数据什么时候获取,通过get方法的重载方法可以设置等待时间。。多个Callable 利用CompletionService对象来接收返回值,通过submit来接受提交的任务!!!接受返回值时谁先有数据就提取谁的数据!通过take 方法放回一个Future对象再调用get方法获取数据。

package concurrent;

import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class CallableTest {
	public static void main(String[] args) throws Exception {
		ExecutorService pool = Executors.newSingleThreadExecutor();
		Future<String> future = pool.submit(new Callable<String>() {
			@Override
			public String call() throws Exception {
				// TODO Auto-generated method stub
				Thread.sleep(3000);
				return "Hello world!";
			}
		});
		
		try {
			System.out.println(future.get(4,TimeUnit.SECONDS));
		} catch (Exception e) {
			e.printStackTrace();
		}
		pool.shutdown();
		submit();
	}
	public static void submit() throws Exception{
		Executor executor = Executors.newCachedThreadPool();
		CompletionService<Integer> service = new ExecutorCompletionService<Integer>(executor);
		for(int i=0;i<10;i++){
			final int sep = i;
			service.submit(new Callable<Integer>() {
				public Integer call() throws Exception {
					Thread.sleep((int)(Math.random()*1000));
					return sep;
				}
			});
		}
		for(int i=0;i<10;i++){
			System.out.println(service.take().get());
		}
	}
}
 

lock,,,普通锁,,以及读写锁,,可以实现读与写之间互斥,读于读之间可以并行,写于写之间也互斥!!

面试题一道,,通过读写锁编写一个缓存类得实际应用

package concurrent;

import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class CacheClass {
	public static void main(String[] args) {
		//test();
	}
	private ReadWriteLock rwl = new ReentrantReadWriteLock();
	private Map<String,Object> cacheData = new HashMap<String,Object>();
	public Object get(String key){
		rwl.readLock().lock();
		Object obj = null;
		try {
			obj = cacheData.get(key);
			if(obj==null){
				rwl.readLock().unlock();
				rwl.writeLock().lock();
				obj = "Shawn";//readDatabase();
				cacheData.put(key, obj);
				rwl.writeLock().unlock();
				rwl.readLock().lock();
			}
		} finally {
			rwl.readLock().unlock();
		}
		
		return obj;
	}
}

 以及通过面向对象设计的一另一道面试题,,子线程执行5次,主线程执行10次,这样循环总共10次。。。通过synchronized关键字修饰子线程和 主线程需要执行的方法封装到一个类当中,通过一个boolean变量来标识子线程和主线程的执行次序。。。然后各自循环10次。。。同样实现两个子线程和 一个主线程来交替执行,这个时候就需要用到显示锁,通过多个条件变量(condition)来实现,,线程1获得锁,执行完释放并通知条件变量2,线程2 获得锁,执行完释放并通知条件变量3,以此类推,,4个或5个线程交替执行也同理!!!

package concurrent;

public class InterViewSubject {
	public static void main(String[] args) {
		init();
	}

	private static void init() {
		final MyData data = new MyData();
		new Thread() {
			public void run() {
				for (int i = 0; i < 10; i++) {
					data.sub();
				}
			}
		}.start();
		for (int i = 0; i < 10; i++) {
			data.main();
		}
	}
}

class MyData {
	private boolean isMain;

	public synchronized void sub() {
		if (!isMain) {
			for (int i = 0; i < 5; i++) {
				System.out.println("sub Thread loop for : " + i);
			}
		} else
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		isMain = true;
		this.notify();
	}

	public synchronized void main() {
		if (isMain) {
			for (int i = 0; i < 10; i++) {
				System.out.println("main Thread loop for : " + i);
			}
		} else
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		isMain = false;
		this.notify();
	}
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值