典型的工作线程结构
下面是典型的工作线程结构,注意中断监测和异常处理,并且在finally中做一些资源回收的工作。
1 /**
2 * 典型线程池工作者线程结构
3 */
4 public void run() {
5 Throwable thrown = null;
6 try {
7 while (!Thread.currentThread().isInterrupted()) {
8 // Run task...
9 }
10 } catch (Throwable e) {
11 thrown = e;
12 } finally {
13 // Exited the thread...
14 }
15 }
ReentrantLock
synchronized使用对象内置的监视器进行同步,这已经可以满足绝大多数的开发情况。如果你还需要更加灵活的锁,比如实现有时限的堵塞,或 者需要在无法获得锁的时候进行一些处理,那么你可以使用ReentrantLock。比如下面的tryLock方法,它在能够获取锁的时候返回true, 不能获取锁的时候返回false,而不会堵塞进程。
1 /** 2 * tryLock() 如果能够获得锁即获得锁并返回true,否则返回false 3 */ 4 public void tryLock() { 5 final int[] data = {0}; 6 ReentrantLock lock1 = new ReentrantLock(); 7 ReentrantLock lock2 = new ReentrantLock(); 8 9 Thread thread1 = new Thread(new Runnable() { 10 @Override 11 public void run() { 12 boolean tag = false; 13 for(int i = 0; i < 10; i++) { 14 try { 15 Thread.sleep(500); 16 } catch (InterruptedException e) { 17 e.printStackTrace(); 18 } 19 while (true) { 20 if (lock1.tryLock()) { 21 try { 22 if (lock2.tryLock()) { 23 try { 24 data[0]++; 25 System.out.println("++"); 26 tag = true; 27 } finally { 28 lock2.unlock(); 29 } 30 } 31 } finally { 32 lock1.unlock(); 33 } 34 } 35 36 if (tag) { 37 tag = false; 38 break; 39 } 40 } 41 } 42 } 43 }); 44 45 Thread thread2 = new Thread(new Runnable() { 46 @Override 47 public void run() { 48 boolean tag = false; 49 for(int i = 0; i < 10; i++) { 50 try { 51 Thread.sleep(400); 52 } catch (InterruptedException e) { 53 e.printStackTrace(); 54 } 55 while (true) { 56 if (lock2.tryLock()) { 57 try { 58 if (lock1.tryLock()) { 59 try { 60 data[0]--; 61 System.out.println("--"); 62 tag = true; 63 } finally { 64 lock1.unlock(); 65 } 66 } 67 } finally { 68 lock2.unlock(); 69 } 70 } 71 72 if (tag) { 73 tag = false; 74 break; 75 } 76 } 77 } 78 } 79 }); 80 81 thread1.start(); 82 thread2.start(); 83 84 try { 85 thread1.join(); 86 } catch (InterruptedException e) { 87 e.printStackTrace(); 88 } 89 try { 90 thread2.join(); 91 } catch (InterruptedException e) { 92 e.printStackTrace(); 93 } 94 95 System.out.println(data[0]); 96 } |
Condition
如果有两个条件谓词在同一个同步对象上使用wait()和notify()进行资源的堵塞等待,那么即有可能会发生信号的丢失,导致死锁。对于这种 情况,要么是用notifyAll()通知等待队列中的进程,这样效率会稍微低一些;另一种方法是使用锁的Condition,
1 /** 2 * Condition 3 */ 4 class ConditionBoundeBuffer<T> { 5 protected final Lock lock = new ReentrantLock(); 6 7 private final Condition notFull = lock.newCondition(); 8 private final Condition notEmpty = lock.newCondition(); 9 10 private final T[] items = (T[]) new Object[3]; 11 private int tail, head, count; 12 13 public void put(T x) throws InterruptedException { 14 lock.lock(); 15 try { 16 while (count == items.length) { 17 notEmpty.await(); 18 } 19 items[tail] = x; 20 if (++tail == items.length) 21 tail = 0; 22 ++count; 23 notEmpty.signal(); 24 } finally { 25 lock.unlock(); 26 } 27 } 28 29 public T take() throws InterruptedException { 30 lock.lock(); 31 try { 32 while (count == 0) { 33 notEmpty.await(); 34 } 35 T x = items[head]; 36 items[head] = null; 37 if (++head == items.length) { 38 head = 0; 39 } 40 --count; 41 notFull.signal(); 42 return x; 43 } finally { 44 lock.unlock(); 45 } 46 } 47 } |