- 浏览: 64864 次
- 性别:
- 来自: 北京
文章分类
最新评论
1. Thread生命周期
// 创建Thread extends Thread或者implements Runnable接口 // 启动Thread thread.start() isAlive(): 可以判断该Thread是否终结 // Thread终结 run()方法执行到return语句,执行到代码最后一行,抛出一个异常 // Thread加入 join(): 用于一个开始执行独立task的thread,来观察该thread是否完成,但是要小心block // 停止Thread - 设定标记 private volatile boolean done = false; public void run() { while(!done) {} } public void setDone() {done=true;} producer.setDone(); // 停止Thread - 中断 public void run() { while(!isInterrupted) {} } producer.interrupt(); // 取得当前thread的引用 Thread.currentThread();
2. 数据同步
// volatile 对变量进行原子操作,使其不会有中间状态出现 可以保证变量每次都从主存储器中读出,但递增和递减不能用于volatile // 锁机制 - java.util.concurrent.locks.Lock private Lock myLock = new ReentrantLock(); try { myLock.lock(); //todo } finally {myLock.unlock();} 定义一个Lock可以多个方法使用,那么意味着这些方法不能异步执行,因为只有一个方法获得锁 每次只有一个方法能够执行 // synchronized也可以锁住快 synchronized(this) {...} 但同步块一般就不能跨方法使用 // Nested Lock 两个不同类的方法相互调用,那么可以使用ReentrantLock来解决此问题,在进入同步块时候, 该方法会判定lock是否获得,而不会产生死锁。ReentrantLock的常见方法 getHoldCount(): 返回当前thread对lock所要求的数量 isLocked(): 是否thread获取lock isHeldByCurrentThread(): 该lock是否由当前thread所有 getQueueLength(): 多少thread在等待取得该lock的估计值 // tryLock() - 返回值可以判定是否获取lock private Lock myLock = new ReentrantLock(); try { if (myLock.tryLock()) { // todo something } else { // todo other task } } finally {myLock.unlock();} // 解决死锁 public void run() { while (!getDone()) { //todo task } } public synchronized boolean getDone() { return done; } public synchronized void setDone(boolean b) { done = b; } // 公平锁 private Lock myLock = new ReentrantLock(true); 会以接近发出时间的顺序来执行
3. Thread Notifiaction
// wait()与notify() public synchronized void run() { while (true) { try { if (done) { wait(); } } } } public synchronized void setDone(boolean b) { done = b; if (!done) { notify(); } } // 使用synchronized块来执行等待通知机制 wait()和notify()必须执行在同步块或同步锁中 private Object doneLock = new Object(); public void run() { synchronized(doneLock) { while (true) { try { if (done) { doneLock.wait(); } else { repaint(); doneLock.wait(100); } } } } } public void setDone(boolean b) { synchronized(doneLock) { done = b; if (!done) doneLock.notify(); } } // 条件变量 Condition应该和Lock绑定在一起 使用await()和signal()代替等待通知机制 private boolean done = true; private Lock lock = new ReentrantLock(); private Condition cv = lock.newCondition(); public void run() { try { lock.lock(); while (true) { try { if (done) { cv.await(); } else { nextCharacter(); cv.await(getPauseTime(), TimeUnit.MILLISECONDS); } } } } finally { lock.unlock(); } } public void setDone(boolean b) { try { lock.lock(); done = b; if (!done) cv.signal(); } } finally { lock.unlock(); } }
4. 极简同步技巧
// 变量存储原理 CPU将数据从主存储器中读到寄存器中,对存储器操作,然后将数据存回主存储器 volatile变量仅能用于单一的载入和存储操作,所以5.0提供了atomic class来代替 // Atomic Class AtomicInteger, AtomicLong, AtomicBoolean, AtomicReference AtomicInteger score = new AtomicInteger(0); AtomicReference<CharacterSource> generator = new AtomicReference<CharacterSource>; generator.getAndSet(newGenerator); // 只有一个Thread取得值并设置该值 generator.get(); // 取得旧值,然后使用compareAndSet()改变旧值 如果需要对一批数据操作,可以把一批数据放入Class,然后操作Classic为Atomic // ThreadLocal 对变量设置为ThreadLocal,可以保证其他Thread不能访问,因而不需要同步,也没有竞争 public abstract class Calculator { protected abstract Object doLocalCalculate(Object param); private static ThreadLocal<HashMap> results = new ThreadLocal<HashMap>() { protected HashMap initialValue() { return new HashMap(); } }; public Object calculate(Object param) { HashMap hm = results.get(); Object o = hm.get(param); if (o != null) return o; o = doLocalCalculate(param); hm.put(param, o); return o; } } public class CalculatorTest extends Calculator implements Runnable { public static void main(String[] args) { int nThreads = 5; for (int i = 0; i < nThreads; i++) { Thread t = new Thread(new CalculatorTest()); t.start(); } } public void run() { for (int i = 0; i < 30; i++) { Integer p = new Integer(i % 5); calculate(p); } } protected Object doLocalCalculate(Object p) { System.out.println("Doing calculation of " + p + " in thread " + Thread.currentThread()); return p; } }
5. 高级同步议题
// 术语 Barrier(屏障): 多个Thread集合,所有Thread到齐才允许继续下去 Condition variable(条件变量): 与Lock相关的变量,用于等待通知机制 Critical section(临界区): synchronized method或block Event variable(事件变量): 条件变量的另一名称 Monitor(监视器): 有些系统是一个Lock,有些系统类似等待通知机制 Mutex(互斥): Lock的另个名称 Semaphore(信号量): 同Lock的功能,能锁住对象 // Semaphore 等同于带计数器的Lock acquire()与release()类似Lock中lock()与unlock()方法 与Lock的区别:构造器的时候 Semaphore(long permits),需要指定可以被允许的数目 // Barrier 可以有两种方法实现Barrier同样的功能 1. 设置Thread等待条件变量,最后达到的Thread通知所有的Thread 2. 使用join()来等待Thread终结 CyclicBarrier(int parties) //构造Barrier await() //等待 // Latch 和Barrieer具有相同功能 CountDownLatch(int count) //构造 await() //等待 countDown() //递减计数,当达到0,所有等待的Thread释放 // 读写Lock Lock lock = new ReentrantReadWriteLock(); lock.writeLock(); lock.readLock(); // 防止死锁的最佳实践是按照顺序获得Lock
6. Collection Class
// java.util.concurrent容器 ConcurrentHashMap: 实现无序Map ConcurrentLinkedQueue: 无限的FIFO Queue ArrayBlockingQueue: 有限FIFO Queue LinkedBlockingQueue: 可是是有限或无线FIFO Queue SynchronousQueue: 有限的FIFO Queue PriorityBlockingQueue: 优先级的Queue DelayQueue: getDelay()取出到期的的元素,没有到期不会取出 // Collections提供同步容器 synchronizedList(list) synchronizedMap(map) synchronizedSet(set) // Iterator与Enumeration 最好使用synchronize过的容器来迭代 // 生产者/消费者模式 /**生产者*/ public class FibonacciProducer implements Runnable { private Thread thr; private BlockingQueue<Integer> queue; public FibonacciProducer(BlockingQueue<Integer> q) { queue = q; thr = new Thread(this); thr.start(); } public void run() { try { for(int x=0;;x++) { Thread.sleep(1000); queue.put(new Integer(x)); System.out.println("Produced request " + x); } } catch (InterruptedException ex) { } } } /**消费者*/ public class FibonacciConsumer implements Runnable { private Fibonacci fib = new Fibonacci(); private Thread thr; private BlockingQueue<Integer> queue; public FibonacciConsumer(BlockingQueue<Integer> q) { queue = q; thr = new Thread(this); thr.start(); } public void run() { int request, result; try { while (true) { request = queue.take().intValue(); result = fib.calculateWithCache(request); System.out.println("Calculated result of " + result + " from " + request); } } catch (InterruptedException ex) { } } } /**测试*/ ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10); new FibonacciProducer(queue); int nThreads = Integer.parseInt(args[0]); for (int i = 0; i < nThreads; i++) new FibonacciConsumer(queue); // 建议 使用Collection class的时候,通过接口来运用 对有竞争的算法,考虑并发的Collection
7. Thread调度
// Thread优先级 Thread.MAX_PRIORITY; Thread.MIN_PRIORITY; Thread.NORM_PRIORITY; Thread t = new Thread(); t.setPriority(0); t.getPriority(); 每个操作系统优先级都不同
8. ThreadPool
// ThreadPoolExecutor execute(Runable task): 执行task shutdown(): 任何送到Executor的task允许执行,不接受新的task shutdownNow(): 没有启动的task不会执行 <T> Future<T> submit(Callable<T> task): 有返回值 <T> Future<T> submit(Runnable task): 有返回值 <T> Future<T> invokeAll(Collection<Callable<T>> tasks): 执行所有task purge(): 查看整个Queue并删除任何被取消的对象 // 定义ThreadPool ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) corePoolSize: 线程池维护线程的最少数量 maximumPoolSize: 线程池维护线程的最大数量 keepAliveTime: 线程池维护线程所允许的空闲时间,如果指定为0,则Thread不会等待就离开 unit: 线程池维护线程所允许的空闲时间的单位 workQueue: 线程池所使用的缓冲队列 一般用LinkedBlockingQueue作为workQueue,不要直接调用该Queue的任何方法,不然ThreadPool的内部运作很混淆 实例: portalThreadPool = new ThreadPoolExecutor(20, 50, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); // Callable可以返回结果或者抛出checked异常
9. Task调度
// TimerTask cancel(): 取消此计时器任务 run(): 此计时器任务要执行的操作 scheduledExecutionTime(): 返回此任务最近实际执行的已安排执行时间 // Timer cancel(): 终止此计时器,丢弃所有当前已安排的任务 purge(): 从此计时器的任务队列中移除所有已取消的任务 schedule(TimerTask task, Date time) 安排在指定的时间执行指定的任务 schedule(TimerTask task, Date firstTime, long period) 安排指定的任务在指定的时间开始进行重复的固定延迟执行 schedule(TimerTask task, long delay) 安排在指定延迟后执行指定的任务 schedule(TimerTask task, long delay, long period) 安排指定的任务从指定的延迟后开始进行重复的固定延迟执行 scheduleAtFixedRate(TimerTask task, Date firstTime, long period) 安排指定的任务在指定的时间开始进行重复的固定速率执行 scheduleAtFixedRate(TimerTask task, long delay, long period) 安排指定的任务在指定的延迟后开始进行重复的固定速率执行 // ScheduledThreadPoolExecutor ScheduledThreadPoolExecutor(int corePoolSize) 使用给定核心池大小创建一个新 ScheduledThreadPoolExecutor ScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler) 使用给定初始参数创建一个新 ScheduledThreadPoolExecutor ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) 使用给定的初始参数创建一个新 ScheduledThreadPoolExecutor ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler) 使用给定初始参数创建一个新 ScheduledThreadPoolExecutor execute(Runnable command): 使用所要求的零延迟执行命令 schedule(Callable<V> callable, long delay, TimeUnit unit) 创建并执行在给定延迟后启用的 ScheduledFuture。 schedule(Runnable command, long delay, TimeUnit unit) 创建并执行在给定延迟后启用的一次性操作 scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) 创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行, 然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推 scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) 创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟 // Callable使用 class TimeoutTask implements Callable { public Integer call() throws IOException { return new Integer(0); } } ScheduledThreadPoolExecutor ste = new ScheduledThreadPoolExecutor(20); Future<Integer> fTaskResult = ste.scheduleAtFixedRate(new TimeoutTask(), 0L, 5L, TimeUnit.SECONDS);
10. I/O
// NIO 使用一个Thread来处理所有的客户端Socket Selector追踪集合点的Scoket和所有开放的客户端Socket 当其中任何Socket有数据,Selector会被通知,未处理数据 的Socket会通过selectedKeys()方法返回 public abstract class TCPNIOServer implements Runnable { protected ServerSocketChannel channel = null; private boolean done = false; protected Selector selector; protected int port = 8000; public void startServer() throws IOException { channel = ServerSocketChannel.open(); channel.configureBlocking(false); ServerSocket server = channel.socket(); server.bind(new InetSocketAddress(port)); selector = Selector.open(); channel.register(selector, SelectionKey.OP_ACCEPT); } public synchronized void stopServer() throws IOException { done = true; channel.close(); } protected synchronized boolean getDone() { return done; } public void run() { try { startServer(); } catch (IOException ioe) { System.out.println("Can't start server: " + ioe); return; } while (!getDone()) { try { selector.select(); } catch (IOException ioe) { System.err.println("Server error: " + ioe); return; } Iterator it = selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey key = (SelectionKey) it.next(); if (key.isReadable() || key.isWritable()) { // Key represents a socket client try { handleClient(key); } catch (IOException ioe) { // Client disconnected key.cancel(); } } else if (key.isAcceptable()) { try { handleServer(key); } catch (IOException ioe) { // Accept error; treat as fatal throw new IllegalStateException(ioe); } } else System.out.println("unknown key state"); it.remove(); } } } protected void handleServer(SelectionKey key) throws IOException { SocketChannel sc = channel.accept(); sc.configureBlocking(false); sc.register(selector, SelectionKey.OP_READ); registeredClient(sc); } protected abstract void handleClient(SelectionKey key) throws IOException; protected abstract void registeredClient(SocketChannel sc) throws IOException; } 以上是采用单Thread来处理,多Thread使用Thread Pool,在请求送到服务器时, handleClient()方法将请求放进thread pool的Queue中,依次处理 public class CalcServer extends TCPNIOServer { static ThreadPoolExecutor pool; class FibClass implements Runnable { long n; SocketChannel clientChannel; ByteBuffer buffer = ByteBuffer.allocateDirect(8); FibClass(long n, SocketChannel sc) { this.n = n; clientChannel = sc; } private long fib(long n) { if (n == 0) return 0L; if (n == 1) return 1L; return fib(n - 1) + fib(n - 2); } public void run() { try { long answer = fib(n); buffer.putLong(answer); buffer.flip(); clientChannel.write(buffer); if (buffer.remaining() > 0) { Selector s = Selector.open(); clientChannel.register(s, SelectionKey.OP_WRITE); while (buffer.remaining() > 0) { s.select(); clientChannel.write(buffer); } s.close(); } } catch (IOException ioe) { System.out.println("Client error " + ioe); } } } protected void handleClient(SelectionKey key) throws IOException { SocketChannel sc = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocateDirect(8); sc.read(buffer); buffer.flip(); long n = buffer.getLong(); FibClass fc = new FibClass(n, sc); pool.execute(fc); } protected void registeredClient(SocketChannel sc) { } public static void main(String[] args) throws Exception { CalcServer cs = new CalcServer(); cs.port = Integer.parseInt(args[0]); int tpSize = Integer.parseInt(args[1]); pool = new ThreadPoolExecutor( tpSize, tpSize, 50000L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); cs.run(); System.out.println("Calc server waiting for requests..."); } }
11. 其他Thread议题
// Thread Group System thread group - Main thread group - Applet thread group 使用group可以对group中所有thread进行操作 // Thread与Security checkAccess(Thread t): 如果不允许调用线程修改thread参数,则抛出SecurityException checkAccess(ThreadGroup g): 如果不允许调用线程修改线程组参数,则抛出SecurityException public void interrupt() { SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkAccess(this); } permission java.security.AllPermission; permission java.security.RuntimePermission "thread"; permission java.lang.RuntimePermission "stopThread"; //stop方法特殊 // Daemon Thread setDaemon(true); // Thread与Class加载 getContextClassLoader() // Thread与异常 Thread的run方法不能抛出未检查型异常,所以需要使用UncaugthExceptionHandler来处理 try { AppTimeoutThread timeThread = new AppTimeoutThread(10000, new MSCtrlTimeoutException( "subSessionIsLoggedOn()")); //超时 timeThread.setUncaughtExceptionHandler(new ChallengeTimeoutHanlder(soapApiMsg, reqPortalMsg, soapAdapter)); timeThread.start(); soapApiMsg = soapAdapter.subSessionIsLoggedOn(reqPortalMsg.getUserIp()); timeThread.cancel(); } catch (Exception e) { log.error("call subSessionIsLoggedOn() timeout", e); } class ChallengeTimeoutHanlder implements UncaughtExceptionHandler { private PortalMsg soapApiMsg; private PortalMsg reqPortalMsg; private SOAPAdapterI soapAdapter; public ChallengeTimeoutHanlder(PortalMsg soapApiMsg, PortalMsg reqPortalMsg, SOAPAdapterI soapAdapter) { this.soapApiMsg = soapApiMsg; this.reqPortalMsg = reqPortalMsg; this.soapAdapter = soapAdapter; } public void uncaughtException(Thread t, Throwable e) { soapApiMsg = soapAdapter.subSessionIsLoggedOn(reqPortalMsg.getUserIp()); } } // Thread与内存 Java的stack默认为1024KB Linux与Windows程序最大内存为2GB Solaris为4GB java -Xss128k MyClass //指定Stack尺寸
12. Thread性能
// JVM参数 Solaris -Xms3500m -Xmx3500m Intel -Xmn1800m -Xms1800m
发表评论
-
Agile Java
2009-09-21 13:48 12811. 代码就是设计 2. ... -
Effective Java
2009-09-04 11:45 8541. 考虑用静态工厂方法代替构造函数 静态工厂方法优点: ... -
Java经典实例(第二版)
2009-06-01 16:33 39741. 获取环境变量 System.getenv(" ... -
Java编程思想(第四版) - 第22章 图形化用户界面
2009-04-03 13:14 812GUI -
Java编程思想(第四版) - 第21章 并发
2009-04-03 11:43 1056并发 -
Java编程思想(第四版) - 第20章 注解
2009-04-03 11:43 775注解 -
Java编程思想(第四版) - 第19章 枚举类型
2009-04-03 11:42 869枚举 -
Java编程思想(第四版) - 第18章 Java I/O系统
2009-04-03 11:41 845IO -
Java编程思想(第四版) - 第17章 容器深入研究
2009-04-03 11:40 880容器 -
Java编程思想(第四版) - 第16章 数组
2009-04-03 11:40 777数组 -
Java编程思想(第四版) - 第15章 泛型
2009-04-03 11:39 678泛型 -
Java编程思想(第四版) - 第14章 类型信息
2009-04-03 11:38 983类型信息 -
Java编程思想(第四版) - 第13章 字符串
2009-04-03 11:37 756字符串 -
Java编程思想(第四版) - 第12章 通过异常处理错误
2009-04-03 11:36 761异常 -
Java编程思想(第四版) - 第11章 持有对象
2009-04-03 11:31 855持有对象 -
Java编程思想(第四版) - 第10章 内部类
2009-04-03 11:30 733内部类 -
Java编程思想(第四版) - 第9章 接口
2009-04-03 11:29 713接口 -
Java编程思想(第四版) - 第8章 多态
2009-04-03 11:29 667多态 -
Java编程思想(第四版) - 第7章 复用类
2009-04-03 11:28 695复用类 -
Java编程思想(第四版) - 第6章 访问权限控制
2009-04-03 11:26 7851. public protectd package priv ...
相关推荐
《JAVA线程第三版》是Java并发编程领域的一本经典著作,主要针对Java线程的深入理解和实践提供了详尽的指导。这本书详细介绍了如何在Java应用程序中有效地使用多线程,以提高程序的性能和可扩展性。Java线程是Java...
书名:Java线程(第三版) 定价:39.00元【定价是指书上的标价,售价是指实际销售价格,请注意两者关系!】 作者:(美)奥克斯,(美)王,公司译 出版社:东南大学出版社 出版日期:2006-03-01 ISBN:9787564102395 ...
在《Java线程第三版》中,作者深入探讨了线程的创建、同步、通信和管理等多个关键方面。这本书的源代码`jthreads3rd.src`提供了丰富的实例和练习,帮助读者理解和掌握Java线程编程的精髓。 1. **线程的创建**:Java...
《详细JAVA线程第三版》是一本专注于Java线程编程的深度指南,旨在帮助开发者深入理解和熟练运用Java平台上的多线程技术。本书全面覆盖了Java线程的基础知识、高级特性以及最佳实践,旨在提升读者在并发编程领域的...
《JAVA线程(第三版)》是一本深入探讨Java多线程编程的权威书籍,针对Java线程的管理和优化提供了详尽的解析。线程在现代计算机编程中扮演着至关重要的角色,尤其是在并发处理和高性能应用中。Java以其强大的线程...
This book is intended for programmers of all levels who need to learn to use threads within Java programs. This includes developers who have previously used Java and written threaded programs; J2SE ...
很好的java线程学习书,本人也在学习中,希望更大家一起进步
java线程第二版中英文 java线程第二版中英文 线程并不是新的概念:许多操作系统和语言都支持它们。在Java出现以前,似乎人人都在谈论线程,却很少有人使用它。用线程编程是技巧性很强的且不可移植。 而在Java中却...
学习java不得不学习java线程,本书中详细解释了线程的低级主题到线程的高级主题,是学习其他知名开源软件(java,如Hadoop等)的必备,希望通过此书能帮助你更好的了解软件的线程组织与操作,从而提高自己对java认识...
《Java线程——第三版》是一本专注于Java多线程编程的专业书籍,旨在帮助开发者深入理解和熟练掌握Java中的并发处理技术。多线程是现代软件开发中的重要概念,尤其是在服务器端应用、分布式系统以及高性能计算等领域...
很好的java线程学习书,本人也在学习中,希望更大家一起进步
1. 线程优先级:Java定义了三个基本优先级(MIN_PRIORITY、NORM_PRIORITY、MAX_PRIORITY),线程可以设置优先级,但实际调度受操作系统影响。 2. 守护线程与用户线程:守护线程不阻碍JVM退出,而用户线程则会阻止JVM...
在Java编程领域,多线程是一项至关重要的技术,它允许程序同时执行多个任务,从而提高系统资源的利用率和程序的响应速度。这份“JAVA多线程编程技术PDF”是学习和掌握这一领域的经典资料,涵盖了多线程的全部知识点...
第三版延续了这一传统,对Java语言的新特性进行了更新,并给出了适应现代编程环境的建议。以下是基于目录和部分内容的关键知识点的详细说明: ### 第一章 介绍 这一章通常会概述本书的目的、目标读者以及书中主要...
"Java语言程序设计第三版-习题答案.pdf" Java语言程序设计第三版-习题答案.pdf是Java语言程序设计的习题答案,涵盖了Java语言的基础知识、语法机制、平台架构、特征等方面。下面是该资源的知识点摘要: Java技术...
《Java多线程编程》第三版是一本深入探讨Java并发编程的权威指南,旨在帮助开发者理解和掌握Java平台上的多线程技术。这本书详尽地介绍了如何有效地利用多核处理器的性能,以及如何在复杂的并发环境中设计和实现高效...