Java Tutorial/Thread/synchronized

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

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(); 
  }
}