Java Concurrency

来源:互联网 发布:淘宝东大门代购哪家好 编辑:程序博客网 时间:2024/05/19 01:33

Interface Runnable

多线程编程时可以继承Thread类,也可以实现Runnable接口。后者需要实现Run()方法,然后:

 (new Thread(new ConcurrencyTest())).start();
Class Thread

该类也实现了Runnable,但是run()方法是空的。

Thread.sleep(int millisecond)

线程休眠xx毫秒(千分之一秒)

Interrupt 和InterruptedException

public void interrupt()方法中断当前线程

public static boolean interrupted() 判断当前线程是否被中断,并重置interrupted状态位。

public boolean interrupt() 判断当前线程是否被中断,不重置interrupted状态位。

InterruptedException: 线程在sleeping, waiting, running是接收到interrupt,抛出此异常。有两种用法:

//主动抛出异常的方法sleeptry {    Thread.sleep(4000);} catch (InterruptedException e) {    // We've been interrupted: no more messages.    return;}//手工抛出异常if (Thread.interrupted()) {    throw new InterruptedException();}
join() : 假如线程在运行,则停止运行等待,直到线程结束。

Synchronized method

 public synchronized void increment() {        c++;    }
对某个object的synchronized method,同时只能有一个线程能执行。
Intrinsic Locks and Synchronization
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.

Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.

Starvation and Livelock

Starvation and livelock are much less common a problem than deadlock, but are still problems that every designer of concurrent software is likely to encounter.
Starvation

Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads. For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked.

A thread often acts in response to the action of another thread. If the other thread's action is also a response to the action of another thread, then livelock may result. As with deadlock, livelocked threads are unable to make further progress. However, the threads are not blocked — they are simply too busy responding to each other to resume work. This is comparable to two people attempting to pass each other in a corridor: Alphonse moves to his left to let Gaston pass, while Gaston moves to his right to let Alphonse pass. Seeing that they are still blocking each other, Alphone moves to his right, while Gaston moves to his left. They're still blocking each other, so...

Object对象的wait()和notify()方法

public final void wait()

Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.In other words, this method behaves exactly as if it simply performs the call wait(0).

The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution. 

This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor. 

public final void notify()

Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.

The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.

This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways:

  • By executing a synchronized instance method of that object.
  • By executing the body of a synchronized statement that synchronizes on the object.
  • For objects of type Class, by executing a synchronized static method of that class.

Only one thread at a time can own an object's monitor.

例子:

public synchronized void guardedJoy() {    // This guard only loops once for each special event, which may not    // be the event we're waiting for.    while(!joy) {        try {            wait();        } catch (InterruptedException e) {}    }    System.out.println("Joy and efficiency have been achieved!");}public synchronized notifyJoy() {    joy = true;    notifyAll();}

例子2:该例子更好地展示了wait(), notifyAll()方法如何互动,可以看到wait()和notifyAll都是Drop对象调用

public class Drop {    private String message;    private boolean empty = true;    public synchronized String take() {        // Wait until message is available.        while (empty) {            try {                //The current thread must own this object's monitor.                // The thread releases ownership of this monitor and waits                // until another thread notifies threads waiting on this object's monitor to wake up                // either through a call to the notify method or the notifyAll method.                // The thread then waits until it can re-obtain ownership of the monitor and resumes execution.                wait();            } catch (InterruptedException e) {                return null;            }        }        //Consume the message then change empty status.        empty = true;        //Notify producer that status has changed.        notifyAll();        return message;    }    public synchronized void put(String message) {        // Wait until message has been retrieved.        while (!empty) {            try {                wait();            } catch (InterruptedException e) {}        }        //Produce the message and change status        empty = false;        this.message = message;        // Notify consumer that status has changed.        /*        Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods.        The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object.        The awakened threads will compete in the usual manner with any other threads that might be actively competing to synchronize on this object;        for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.        This method should only be called by a thread that is the owner of this object's monitor.        See the notify method for a description of the ways in which a thread can become the owner of a monitor.        */        notifyAll();    }}
Immutable Objects

An object is considered immutable if its state cannot change after it is constructed. Maximum reliance on immutable objects is widely accepted as a sound strategy for creating simple, reliable code.

Immutable objects are particularly useful in concurrent applications. Since they cannot change state, they cannot be corrupted by thread interference or observed in an inconsistent state.

Programmers are often reluctant to employ immutable objects, because they worry about the cost of creating a new object as opposed to updating an object in place. The impact of object creation is often overestimated, and can be offset by some of the efficiencies associated with immutable objects. These include decreased overhead due to garbage collection, and the elimination of code needed to protect mutable objects from corruption.


A Strategy for Defining Immutable Objects

Don't provide "setter" methods — methods that modify fields or objects referred to by fields.
Make all fields final and private.
Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
If the instance fields include references to mutable objects, don't allow those objects to be changed:
    Don't provide methods that modify the mutable objects.
    Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.

例子:

final public class ImmutableRGB {    // Values must be between 0 and 255.    final private int red;    final private int green;    final private int blue;    final private String name;    private void check(int red,                       int green,                       int blue) {        if (red < 0 || red > 255            || green < 0 || green > 255            || blue < 0 || blue > 255) {            throw new IllegalArgumentException();        }    }    public ImmutableRGB(int red,                        int green,                        int blue,                        String name) {        check(red, green, blue);        this.red = red;        this.green = green;        this.blue = blue;        this.name = name;    }    public int getRGB() {        return ((red << 16) | (green << 8) | blue);    }    public String getName() {        return name;    }    public ImmutableRGB invert() {        return new ImmutableRGB(255 - red,                       255 - green,                       255 - blue,                       "Inverse of " + name);    }}

0 0
原创粉丝点击