Java Tutorial/Thread/synchronized
Содержание
- 1 A synchronized collection with Collections.synchronizedCollection
- 2 creating a piped communications system between two threads.
- 3 Determining If the Current Thread Is Holding a Synchronized Lock
- 4 Flag Communication
- 5 guarantee that threads are woken in the same order in which they waited
- 6 Handle concurrent read/write: use synchronized to lock the data
- 7 Test Synchronized method
- 8 Test Unsynchronized method
- 9 This program is not synchronized.
- 10 This program uses a synchronized block.
- 11 wait() and notify() must only be issued inside a synchronized block
- 12 Waiting on an object
A synchronized collection with Collections.synchronizedCollection
<source lang="java">
import java.util.Collection; import java.util.Collections; import java.util.Set; import java.util.TreeSet; class MyThread implements Runnable {
Thread t; Collection<String> col; MyThread(Collection<String> c) { col = c; t = new Thread(this, "MyThread"); t.start(); } public void run() { try { Thread.sleep(100); col.add("D"); synchronized (col) { for (String str : col) { System.out.println("MyThread: " + str); Thread.sleep(50); } } } catch (Exception exc) { exc.printStackTrace(); } }
} public class Main {
public static void main(String args[]) throws Exception { Set<String> tsStr = new TreeSet<String>(); Collection<String> syncCol = Collections.synchronizedCollection(tsStr); syncCol.add("A"); syncCol.add("B"); syncCol.add("C"); new MyThread(syncCol); synchronized (syncCol) { for (String str : syncCol) { System.out.println("Main thread: " + str); Thread.sleep(500); } } }
}</source>
creating a piped communications system between two threads.
<source lang="java">
import java.io.IOException; import java.io.PipedReader; import java.io.PipedWriter; public class MainClass extends Thread {
public static void main(String[] args) throws IOException { PipedWriter pw = new PipedWriter(); PipedReader pr = new PipedReader(pw); int ch; try { for (int i = 0; i < 15; i++) pw.write(" A" + i + "\n"); while ((ch = pr.read()) != -1) System.out.print((char) ch); } catch (IOException e) { } }
}</source>
Determining If the Current Thread Is Holding a Synchronized Lock
<source lang="java">
public class Main {
public static void main(String[] argv) throws Exception { Object o = new Object(); System.out.println(Thread.holdsLock(o)); synchronized (o) { System.out.println(Thread.holdsLock(o)); } }
}</source>
Flag Communication
<source lang="java">
public class FlagComm {
public static void main(String args[]) { FlagSend s = new FlagSend(); FlagRec r = new FlagRec(s); Thread st = new Thread(s); Thread rt = new Thread(r); rt.setDaemon(true); st.start(); rt.start(); try { while (s.isValid) { Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } }
} class FlagSend implements Runnable {
volatile int theValue; volatile boolean isValid; public void run() { for (int i = 0; i < 5; i++) { while (isValid) { Thread.yield(); } theValue = (int) (Math.random() * 256); System.out.println("sending " + theValue); isValid = true; } }
} class FlagRec implements Runnable {
FlagSend theSender; public FlagRec(FlagSend sender) { theSender = sender; } public void run() { while (true) { while (!theSender.isValid) { Thread.yield(); } System.out.println("received " + theSender.theValue); theSender.isValid = false; } }
}</source>
guarantee that threads are woken in the same order in which they waited
<source lang="java">
import java.util.Vector; public class Wake {
private Vector<Object> stopped = new Vector<Object>(); public void stopOne() { Object myLock = new Object(); synchronized (myLock) { stopped.addElement(myLock); try { myLock.wait(); } catch (InterruptedException e) { } } } public void wakeOne() { Object theLock = null; synchronized (stopped) { if (stopped.size() != 0) { theLock = stopped.firstElement(); stopped.removeElementAt(0); } } if (theLock != null) { synchronized (theLock) { theLock.notify(); } } } public static void main(String args[]) { Wake queue = new Wake(); Runnable r = new RunThis(queue); Thread t; for (int i = 0; i < 10; i++) { t = new Thread(r); t.start(); } for (int i = 0; i < 11; i++) { try { Thread.sleep((long) (Math.random() * 1000)); } catch (InterruptedException e) { } System.out.println("About to wake one thread"); queue.wakeOne(); } }
} class RunThis implements Runnable {
Wake w; public RunThis(Wake w) { this.w = w; } public void run() { System.out.println("Thread starting, name is " + Thread.currentThread().getName()); w.stopOne(); System.out.println("Thread woken up, name is " + Thread.currentThread().getName()); }
}</source>
Handle concurrent read/write: use synchronized to lock the data
<source lang="java">
import java.util.Iterator; import java.util.Vector; public class Main {
public static void main(String[] args) throws Exception { Vector data = new Vector(); new Producer(data).start(); new Consumer(data).start(); }
} class Producer extends Thread {
Vector data; Producer(Vector data) { super("Producer"); this.data = data; } public void run() { while (true) { data.addElement(new Object()); if (data.size() > 1000) data.removeAllElements(); } }
} class Consumer extends Thread {
Vector data; Consumer(Vector data) { super("Consumer"); this.data = data; } public void run() { while (true) { synchronized (data) { Iterator it = data.iterator(); while (it.hasNext()) it.next(); } } }
}</source>
Test Synchronized method
<source lang="java">
public class TestSynchronized {
int taskID; public synchronized void performATask(int val) { taskID = val; print("before: " + taskID); try { Thread.sleep(4000); } catch (InterruptedException x) { } print("after: " + taskID); } public static void print(String msg) { System.out.println(Thread.currentThread().getName() + ": " + msg); } public static void main(String[] args) throws Exception{ final TestSynchronized tus = new TestSynchronized(); Runnable runA = new Runnable() { public void run() { tus.performATask(1); } }; Thread ta = new Thread(runA, "threadA"); ta.start(); Thread.sleep(2000); Runnable runB = new Runnable() { public void run() { tus.performATask(2); } }; Thread tb = new Thread(runB, "threadB"); tb.start(); }
}</source>
Test Unsynchronized method
<source lang="java">
public class TestUnsynchronized {
int taskID; public void doAction(int val) { print("entering doAction()"); taskID = val; print("doAction() taskID " + taskID); try { Thread.sleep(4000); } catch (InterruptedException x) { } print("doAction() sleep after taskID " + taskID); print("leaving performATask()"); } public static void print(String msg) { String threadName = Thread.currentThread().getName(); System.out.println(threadName + ": " + msg); } public static void main(String[] args) throws Exception { final TestUnsynchronized tus = new TestUnsynchronized(); Runnable runA = new Runnable() { public void run() { tus.doAction(3); } }; Thread ta = new Thread(runA, "threadA"); ta.start(); Thread.sleep(2000); Runnable runB = new Runnable() { public void run() { tus.doAction(7); } }; Thread tb = new Thread(runB, "threadB"); tb.start(); }
}</source>
This program is not synchronized.
<source lang="java">
class Callme {
void call(String msg) { System.out.print("[" + msg); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Interrupted"); } System.out.println("]"); }
} class Caller implements Runnable {
String msg; Callme target; Thread t; public Caller(Callme targ, String s) { target = targ; msg = s; t = new Thread(this); t.start(); } public void run() { target.call(msg); }
} class Synch {
public static void main(String args[]) { Callme target = new Callme(); Caller ob1 = new Caller(target, "Hello"); Caller ob2 = new Caller(target, "Synchronized"); Caller ob3 = new Caller(target, "World"); try { ob1.t.join(); ob2.t.join(); ob3.t.join(); } catch (InterruptedException e) { System.out.println("Interrupted"); } }
}</source>
This program uses a synchronized block.
<source lang="java">
class Callme {
void call(String msg) { System.out.print("[" + msg); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Interrupted"); } System.out.println("]"); }
} class Caller implements Runnable {
String msg; Callme target; Thread t; public Caller(Callme targ, String s) { target = targ; msg = s; t = new Thread(this); t.start(); } public void run() { synchronized (target) { // synchronized block target.call(msg); } }
} class Synch1 {
public static void main(String args[]) { Callme target = new Callme(); Caller ob1 = new Caller(target, "Hello"); Caller ob2 = new Caller(target, "Synchronized"); Caller ob3 = new Caller(target, "World"); try { ob1.t.join(); ob2.t.join(); ob3.t.join(); } catch (InterruptedException e) { System.out.println("Interrupted"); } }
}</source>
wait() and notify() must only be issued inside a synchronized block
<source lang="java">
public class WaitComm {
public static void main(String args[]) { WFlagSend s = new WFlagSend(); WFlagRec r = new WFlagRec(s); Thread st = new Thread(s); Thread rt = new Thread(r); rt.setDaemon(true); st.start(); rt.start(); try { st.join(); while (s.isValid) { Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } }
} class WFlagSend implements Runnable {
volatile int theValue; boolean isValid; public void run() { for (int i = 0; i < 5; i++) { synchronized (this) { while (isValid) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } theValue = (int) (Math.random() * 256); System.out.println("sending " + theValue); synchronized (this) { isValid = true; this.notify(); } } }
} class WFlagRec implements Runnable {
WFlagSend theSender; public WFlagRec(WFlagSend sender) { theSender = sender; } public void run() { while (true) { synchronized (theSender) { while (!theSender.isValid) { try { theSender.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } System.out.println("received " + theSender.theValue); synchronized (theSender) { theSender.isValid = false; theSender.notify(); } } }
}</source>
Waiting on an object
<source lang="java">
public class Main {
public static void main(String str[]) { final Object monitor = new Object(); new Thread() { public void run() { try { synchronized (monitor) { System.out.println("10 seconds ..."); monitor.wait(10000); System.out.println("Wait over"); } } catch (Throwable t) { t.printStackTrace(); } } }.start(); }
}</source>