1.perface:
singleThread 是单一线程模式:即在单一的时间片上只允许一个线程通过。
2.service:code:
demo01: 单人过门问题:
情景如下:有一个独木桥,每次只允许一个人通过,现有三个人过桥,代码实现过桥循序 只要名字首字母和国家首字母相同即可通过
Gate class:
public class Gate { private int counter = 0; private String name = "Nobody"; private String address = "Nowhere"; public synchronized void pass(String name, String address) { this.counter++; this.name = name; try { Thread.sleep(1000); } catch (InterruptedException e) { } this.address = address; check(); } public synchronized String toString() { return "No." + counter + ": " + name + ", " + address; } private void check() { if (name.charAt(0) != address.charAt(0)) { System.out.println("***** BROKEN ***** " + toString()); } }}
userThread如下:
public class testsingleThreadUserThread extends TestRunnable {private final Gate gate;private final String myname;private final String myaddress;public testsingleThreadUserThread(Gate gate, String myname, String myaddress) { this.gate = gate; this.myname = myname; this.myaddress = myaddress;}@Overridepublic void runTest() throws Throwable { // TODO Auto-generated method stub System.out.println(myname + " BEGIN"); while (true) { gate.pass(myname, myaddress); }}测试如下:
@Testpublic void singlethreadTest() throws Throwable { System.out.println("Testing Gate, hit CTRL+C to exit."); TestRunnable tr1, tr2, tr3; Gate gate = new Gate(); tr1 = new testsingleThreadUserThread(gate, "Alice", "Alaska"); tr2 = new testsingleThreadUserThread(gate, "Bobby", "Brazil"); tr3 = new testsingleThreadUserThread(gate, "Chris", "Canada"); TestRunnable[] trs = { tr1,tr2,tr3 }; MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(trs); mttr.runTestRunnables();}
demo02:死锁(deadLock):
情景: 桌子上的对应的spoon和fork,alice 和bob 同时去吃饭,很显然他们的必须同时取得spoon和fork才能吃饭。
Tool:
public class Tool { private final String name; public Tool(String name) { this.name = name; } public String toString() { return "[ " + name + " ]"; }}
public class EaterThreadTest extends TestRunnable { private String name; private final Tool lefthand; private final Tool righthand; public EaterThreadTest(String name, Tool lefthand, Tool righthand) { this.name = name; this.lefthand = lefthand; this.righthand = righthand; } // public void run() { // while (true) { // eat(); // } // } public void eat() { synchronized (lefthand) { System.out.println(name + " takes up " + lefthand + " (left)."); synchronized (righthand) { System.out.println(name + " takes up " + righthand + " (right)."); System.out.println(name + " is eating now, yam yam!"); System.out.println(name + " puts down " + righthand + " (right)."); } System.out.println(name + " puts down " + lefthand + " (left)."); } } @Override public void runTest() throws Throwable { // TODO Auto-generated method stub while (true) { this.eat(); } }}
public class testMain { @Test public void testdeadlick() throws Throwable { System.out.println("Testing EaterThread, hit CTRL+C to exit."); Tool spoon = new Tool("Spoon"); Tool fork = new Tool("Fork"); TestRunnable tr1, tr2; tr2 = (TestRunnable) new EaterThreadTest("Boby", spoon, fork); tr1 = (TestRunnable) new EaterThreadTest("Alice", spoon, fork); TestRunnable[] trs = { tr1, tr2 }; MultiThreadedTestRunner multiThreadedTestRunner = new MultiThreadedTestRunner( trs); multiThreadedTestRunner.runTestRunnables(); }测试时,问题是:spoon和fork应该是一个整体,两个进程访问时,可能会将持有对方进程资源。也就是竞争不可剥夺资源。
也就是说:其作为整体资源才具有意义。
public class Pair { private final Tool lefthand; private final Tool righthand; public Pair(Tool lefthand, Tool righthand) { this.lefthand = lefthand; this.righthand = righthand; } public String toString() { return "[ " + lefthand + " and " + righthand + " ]"; }}
demo03 :互斥对象
为了解决共享临界区的资源问题,使用Mutex类来实现对临界资源的加锁和解锁。
加锁时,标志该进程将要占用该资源。其他的进程则要等待。
解锁时,表示无进程占用该资源,唤醒所有线程去占用资源。
因此,在可能线程争用的方法中将逻辑进行先加锁后解锁处理即可。
public final class Mutex { private boolean busy = false; public synchronized void lock() { while (busy) { try { wait(); } catch (InterruptedException e) { } } busy = true; } public synchronized void unlock() { busy = false; notifyAll(); }}
互斥对象补充
一个较为完善的互斥对象的结构:包含了一个使用数量,一个线程ID,一个计数器 使用数量是指有多少个线程在调用该对象,线程ID是指互斥对象维护的线程的ID 计数器表示当前线程调用该对象的次数:
public final class Mutex { private long locks = 0; private Thread owner = null; public synchronized void lock() { Thread me = Thread.currentThread(); while (locks > 0 && owner != me) { try { wait(); } catch (InterruptedException e) { } } // locks == 0 || owner == me owner = me; locks++; } public synchronized void unlock() { Thread me = Thread.currentThread(); if (locks == 0 || owner != me) { return; } // locks > 0 && owner == me locks--; if (locks == 0) { owner = null; notifyAll(); } }}
3.reference:
java多线程设计模式详解:
4.enclosure download
【notes】:测试环境为groboutils: