Java Tutorial/Thread/synchronized

Материал из Java эксперт
Перейти к: навигация, поиск

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>