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
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);
}
}
}
}
creating a piped communications system between two threads.
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) {
}
}
}
Determining If the Current Thread Is Holding a Synchronized Lock
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));
}
}
}
Flag Communication
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;
}
}
}
guarantee that threads are woken in the same order in which they waited
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());
}
}
Handle concurrent read/write: use synchronized to lock the data
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();
}
}
}
}
Test Synchronized method
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();
}
}
Test Unsynchronized method
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();
}
}
This program is not synchronized.
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");
}
}
}
This program uses a synchronized block.
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");
}
}
}
wait() and notify() must only be issued inside a synchronized block
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();
}
}
}
}
Waiting on an object
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();
}
}