Java------Multithreading: producer and Consumer 2 (JDK1.5 upgrade)

Source: Internet
Author: User

This article is written about JDK1.5 's upgraded producers and consumers.


Workaround after Java upgrade:

Lock



Java.util.concurrent.locks
Interface Lock
All known implementation classes:
Reentrantlock,reentrantreadwritelock.readlock,reentrantreadwritelock.writelock
Lock

LockImplementations provide a wider synchronized range of locking operations than can be obtained using methods and statements. This implementation allows for a more flexible structure that can have very different properties and can support multiple related Condition objects.

A lock is a tool that controls the access of multiple threads to a shared resource. Typically, a lock provides exclusive access to a shared resource. Only one thread can get a lock at a time, and all access to the shared resource requires a lock first. However, some locks may allow concurrent access to shared resources, such as ReadWriteLock read locks.

synchronizedThe use of a method or statement provides access to an implicit monitor lock associated with each object, but forces all lock acquisition and deallocation to appear in a block structure: When multiple locks are acquired, they must be disposed in reverse order, and all locks must be released in the same lexical scope as all locks are fetched.

Although synchronized the scope mechanism of methods and statements makes it much easier to program with monitor locks, it also helps avoid many common programming errors involving locks, but sometimes requires a more flexible approach to using locks. For example, some algorithms that traverse data results for concurrent access require "Hand-over-hand" or "Chain locking": Get the lock for node A, then get the lock for node B, then release A and get C, then release B and get D, and so on. Lockthe implementation of the interface allows locks to be acquired and freed within different scopes, and allows multiple locks to be fetched and freed in any order, thereby supporting the use of this technique.

With the increase of flexibility, it also brings more responsibility. synchronizedthe lock auto-release feature that occurs when you use methods and statements is lost without using block structure locks. In most cases, the following statements should be used:

     Lock L = ...;      L.lock ();     try {         //access the resource protected by this lock     } finally {         l.unlock ();     
When locking and unlocking occurs in different scopes, care must be taken to ensure that all code executed while holding the lock is protected with try-finally or try-catch to ensure that the lock is released when necessary.

LockImplementations provide synchronized additional functionality that is not available using methods and statements, including providing a non-block structure to acquire a lock attempt ( tryLock() ), an attempt to get an interruptible lock (), lockInterruptibly() and an attempt to obtain a timeout failure lock ( tryLock(long, TimeUnit) ).

LockClasses can also provide a completely different behavior and semantics from implicit monitor locks, such as guaranteed sorting, non-reentrant usage, or deadlock detection. If an implementation provides such a special semantics, the implementation must record these semantics.

Note that an Lock instance is just an ordinary object, which itself can be synchronized used as a target in a statement. Getting the Lock monitor lock for an instance lock() does not have a special relationship with any method that invokes the instance. To avoid confusion, it is recommended that you never use an instance in this way, except in its own implementation Lock .

Unless otherwise noted, passing a value for any parameter null will result in a throw NullPointerException .

Memory synchronization

All Lock implementations must implement the same memory synchronization semantics provided with the built-in monitor lock, as described in the Java Language specification, third Edition (17.4 Memory Model):

    • A successful lock operation has the same memory synchronization effect as a successful Lock operation.
    • A successful unlock operation has the same memory synchronization effect as a successful Unlock operation.
No memory synchronization effects are required for unsuccessful lock and unlock operations and for the re-entry lock/unlock operation. Implementation considerations

Three forms of lock acquisition (interruptible, non-disruptive, and timed) may vary in their performance characteristics, sequencing guarantees, or other implementation quality. Also, for a given Lock class, there may be no interruption in the ability to acquire locks in progress. Therefore, the implementation does not require the same guarantees or semantics to be defined for all three forms of lock acquisition, nor does it require support to interrupt in-progress lock fetching. Implementations must clearly record the semantics and guarantees provided by each locking method. You must also adhere to the interrupt semantics defined in this interface to provide support for lock acquisition interrupts: Full support for interrupts, or support for interrupts only when entering methods.

Since interrupts usually mean cancellation, and often very little interruption checking, implementations may prefer to respond to an interrupt relative to the normal method return. This is true even if the interrupt that occurs after another operation may release the lock. The implementation should log this behavior.

Start from the following versions:
1.5


Method Summary
 void lock()
Gets the lock.
 void lockInterruptibly()
Gets the lock if the current thread is not interrupted.
 Condition newCondition()
Returns a new instance bound to this Lock instance Condition .
 boolean tryLock()
The lock is acquired only if the call to Shi is idle.
 boolean tryLock(long time,TimeUnit unit)
Gets the lock if the lock is idle for a given wait time, and the current thread is not interrupted.
 void unlock()
Release the lock.



Lock appears to have lock () and unlock () to acquire locks and release locks in a method that replaces synchronized lock. Unlike synchronized, the process of acquiring locks and releasing locks is more visible. It also feels more convenient when you use them.

Lock supports related objects---Condition


Java.util.concurrent.locks
Interface Condition
All known implementation classes:
Abstractqueuedlongsynchronizer.conditionobject,abstractqueuedsynchronizer.conditionobject
Condition

ConditionThe Object monitor methods ( wait , notify and notifyAll ) are decomposed into distinct objects to Lock provide multiple wait sets (Wait-set) for each object by combining these objects with any implementation. This replaces the use of Lock synchronized methods and statements, Condition replacing the use of the Object monitor method.

A condition (also known as a conditional queue or condition variable ) provides a means for a thread to suspend the thread (that is, let it "wait") until another thread that a state condition might now be true notifies it. Because access to this shared state information occurs in different threads, it must be protected so that a form of lock is associated with that condition. The primary property for waiting to provide a condition is to atomically release the associated lock and suspend the current thread as if it were Object.wait done.

ConditionAn instance is essentially bound to a lock. To obtain an instance for a specific Lock instance Condition , use its newCondition() method.

As an example, assume that there is a binding buffer that it supports put and take methods. If an attempt is made to perform an operation on an empty buffer, the take thread will block until an item becomes available, and if an attempt is made to perform an operation on a full buffer, the put thread will block until the space becomes available. We like to save threads and threads in a separate wait set put take , so that you can take advantage of the best planning when an item or space in the buffer becomes available, notifying only one thread at a time. You can use two Condition instances to do this.

Class Boundedbuffer {Final Lock lock = new Reentrantlock ();Final Condition notfull =lock.newcondition ();Final Condition Notempty =lock.newcondition ();Final object[] items = new OBJECT[100];   int Putptr, takeptr, Count; public void put (Object x) throws Interruptedexception {Lock.lock (); try {while (count = = items.length)notfull.await ();ITEMS[PUTPTR] = x;       if (++putptr = = items.length) putptr = 0; ++count;notempty.signal (); } finally {Lock.unlock (); }} public Object take () throws Interruptedexception {Lock.lock (); try {while (count = = 0)notempty.await ();Object x = items[takeptr];       if (++takeptr = = items.length) takeptr = 0; --count;notfull.signal ();return x;} finally {Lock.unlock (); }}  }
ArrayBlockingQueueclass provides this functionality, so there is no reason to implement this example class. )

ConditionImplementations can provide Object behavior and semantics that differ from the monitor method, such as a guaranteed sort of notification, or a lock that does not need to be maintained when the notification is executed. If an implementation provides such a special semantics, the implementation must record these semantics.

Note that the Condition instances are just plain objects that themselves can be used as synchronized targets in the statement, and can invoke their own wait and notification monitor methods. Gets Condition The monitor lock for an instance or uses its monitor method, with no specific relationship to getting and the Condition related Lock or using its waiting and signalling methods. To avoid confusion, it is recommended that you do not use instances in this way except in their own implementations Condition .

Unless otherwise noted, passing a value for any parameter null will result in a throw NullPointerException .

Implementation considerations

When waiting Condition , " spurious wakeup " is allowed, which usually serves as a concession to the underlying platform semantics. For most applications, this has a small practical impact because it Condition should always be waiting in a loop and testing the status declaration that is waiting. An implementation is free to remove possible spurious wakes, but it is recommended that application programmers always assume that these spurious wakes can occur and therefore always wait in a loop.

Three forms of conditional wait (interruptible, non-disruptive, and timed out) implementations on some platforms and their performance characteristics may vary. In particular, it may be difficult to provide these features and maintain specific semantics, such as ordering guarantees. Further, the ability to actually suspend the interrupt process is not always feasible on all platforms.

Therefore, an implementation is not required to define exactly the same guarantees or semantics for all three forms of waiting, nor does it require the actual suspension of the thread to be supported.

Requires implementation to clearly document the semantics and guarantees provided by each wait method, which must conform to the interrupt semantics defined in this interface when an implementation does not support the suspend of a thread.

Since interrupts usually mean cancellation, and often very little interruption checking, implementations can respond to interrupts before the return of the normal method. This is true even if the interrupt that occurs after another operation may release the lock. The implementation should log this behavior.

Start from the following versions:
1.5
Method Summary
 void await()
Causes the current thread to wait until it receives a signal or is interrupted.
 boolean await(long time,TimeUnit unit)
Causes the current thread to wait until it receives a signal, is interrupted, or arrives at a specified wait time.
 long awaitNanos(long nanosTimeout)
Causes the current thread to wait until it receives a signal, is interrupted, or arrives at a specified wait time.
 void awaitUninterruptibly()
Causes the current thread to remain in a wait state until it receives a signal.
 boolean awaitUntil(Date deadline)
Causes the current thread to wait until it receives a signal, is interrupted, or reaches a specified deadline.
 void signal()
Wakes up a waiting thread.
 void signalAll()
Wakes all waiting threads.


Lock replaces the use of the Synchronized method and the statement, and Condition replaces the use of the Object monitor method.

A multithreaded upgrade solution is available in JDK1.5.

Synchronizes the synchronized

Replaced with lock operation

Replaces the Wait,notify,notifyall method in object with the condition object.

The object can be obtained through a lock lock.

The most important thing is that lock can bind multiple locks, whereas synchronized can only bind one object.

It is because lock can bind multiple objects that it realizes waking only the thread of the party without waking the other thread.

The practice is to define two condition objects, an object representing the producer, an object representing the consumer, waking the thread with the producer's object, waking the producer's thread, and the same consumer's thread that wakes up the consumer's object.


Import Java.util.concurrent.locks.*;class Resource {private String Name;private string sex;private Boolean flag = False;p Rivate Lock lock = new Reentrantlock ();p rivate Condition Condition_pro = lock.newcondition ();p rivate Condition Condition_ con = lock.newcondition ();p ublic void Set (string name, String sex) throws Interruptedexception {lock.lock (); try {while (fl AG = = true) {condition_pro.await ();} THIS.name = name + "--" + sex; System.out.println (Thread.CurrentThread (). GetName () + "---producer---" + this.name); flag = True;condition_con.signal ();} finally {Lock.unlock ();}} public void Out () throws Interruptedexception {Lock.lock (), try {while (flag = = False) {condition_con.await ();} System.out.println (Thread.CurrentThread (). GetName () + "--consumer--" + this.name); flag = False;condition_pro.signal ();} finally {Lock.unlock ();}}} Class Producer implements Runnable {private Resource resource;private int num = 1; Producer (Resource Resource) {this.resource = Resource;} public void Run () {while (true) {if (num = = 1) {try {resource.set ("Lili", "female Female"),} catch (Interruptedexception e) {//TODO auto-generated catch Blocke.printstacktrace ( );}} else {try {resource.set ("Mike", "Man"),} catch (Interruptedexception e) {//TODO auto-generated catch Blocke.printstacktr Ace ();}}}} Class Consumer implements Runnable{private Resource Resource; Consumer (Resource Resource) {this.resource = Resource;} public void Run () {while (true) {try {resource.out ()} catch (Interruptedexception e) {//TODO auto-generated catch Blocke . Printstacktrace ();}}} Class Communicate {public static void main (string[] args) {Resource Resource = new Resource (); Producer Producer = new Producer (Resource); Consumer Consumer = new Consumer (Resource); thread T1 = new Thread (producer); Thread t2 = new Thread (producer); thread t3 = new thread (consumer); thread T4 = new Thread (consumer); T1.start (); T2.start (); T3.start (); T4.start ();}}



Java------Multithreading: producer and Consumer 2 (JDK1.5 upgrade)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.