The recent bias is concurrent, because there will be a lot of messages in the future, so when multiple threads, such as JMS, manipulate the data, it is important to take care of the shared variables to prevent thread insecurity.
A
First of all, simulate the sending and receiving of information. The scenario is this:
Just like I did before the message sent, one is the server, one is the client. Send, to ensure that information 100% sent to the client, then to the client, the client returned a message to tell the server, has been received. When the server has not received the message returned by the client, the server will continue to send this information until the client sends back a confirmation message, and then delete the duplicate sent message.
To simulate this scenario, here are two threads to write, one to send, one to receive, the information to send, to save to thread-safe objects, to prevent thread-safety problems, and to use Concurrenthashmap.
Send code:
Packagecom. Testthread;/** * @author Schrödinger hungry Cat **/ImportJava.util.Map.Entry;ImportJava.util.concurrent.ConcurrentHashMap; Public classPushthreadextendsThread {@Override Public voidrun () {//TODO auto-generated Method Stub Try{sleep (6000); while(MainThread.pushmessage.size () >0){ //re-send message for(Entry<integer, string>HashMap:MainThread.pushmessage.entrySet ()) {System.out.println ("Message ID:" +hashmap.getkey () + "not sent successfully, Resend here:" +Hashmap.getvalue ()); } Sleep (1000); } } Catch(interruptedexception e) {//TODO auto-generated Catch blockE.printstacktrace (); } } }
Send code, is constantly traversing the memory object Councurrenthashmap, from which to take out information, constantly resend. Where Mainthread.pushmessage is a memory object and is defined in the last piece of code.
When the message is acknowledged, another thread deletes the memory object.
Code to delete:
Packagecom. Testthread;/** * @author Schrödinger hungry Cat **/ImportJava.util.Map.Entry; Public classRemovethreadextendsThread {@Override Public voidrun () {//TODO auto-generated Method Stub Try { for(inti = 0; I < 10000; i++) {Sleep (2000); for(Entry<integer, string>Map:MainThread.pushmessage.entrySet ()) { if(Map.getkey () = =i) {System.out.println ("Successfully received ID:" +map.getkey () + "Return information, delete this element"); MainThread.pushmessage.remove (Map.getkey ()); }} System.out.println ("The number of elements in the memory object is:" +MainThread.pushmessage.size ()); } } Catch(interruptedexception e) {//TODO auto-generated Catch blockE.printstacktrace (); } } }
Here is to delete the received information and then remove it from memory and send it again.
Then write a main class entry:
Packagecom. Testthread;/** * @author Schrödinger hungry Cat **/ImportJava.util.concurrent.ConcurrentHashMap; Public classMainthread { Public StaticConcurrenthashmap<integer, string> pushmessage=NewConcurrenthashmap<integer,string>(); Public Static voidMain (string[] args) { for(inti = 0; I < 10; i++) {pushmessage.put (I,"The message is a message with an ID of" +i+ "); } Thread Pushthread=NewPushthread (); Thread Remove=NewRemovethread (); Pushthread.start (); Remove.start (); for(inti = 10; I < 20; i++) {pushmessage.put (I,"Another wave arrives, the message is the message ID" +i+ "); } }}
So two threads can take turns doing their own things without causing data security problems. In this way, combined with ANDROIDPN's push mechanism, it will be more in line with the actual production of the application.
(b) Multi-threaded synchronization counter
Multi-threaded synchronization counter, according to the truth can also be processed according to the above way, define a variable like concurrenthashmap. In Java, there are also other variables, atomic variables Atomic, atomiclong,atomicinteger,atomicreference.
If in the multi-threaded environment to give some values to assign a unique ID, this time, it is necessary to consider the ID of the security issue, that is, the consistency of the problem, can not be repeated. Here are two implementations of the code:
Packagecom.test; Public classThreadCount { Public Static voidMain (string[] args) {thread[] threads=Newthread[10000]; for(inti = 0; I < 10000; i++) {Threads[i]=NewAthread (); Threads[i].start (); } }}classAthreadextendsthread{@Override Public voidrun () {//TODO auto-generated Method Stub@SuppressWarnings ("Unused") Counter Counter=NewCounter (); System.out.println (Counter.calnum ()); } }classcounter{Private Static Longnum; PublicCounter () {synchronized(Counter.class) {num++; } } Public Static synchronized LongCalnum () {returnnum; }}
Here, 10,000 threads are created, each of which accesses the counter and increments the values in the construction method.
In the counter, there are two times used in synchronization, many people say that with synchronization, often impact on performance. So, with the second atom variable, this performance should be better.
Code:
Packagecom.test;ImportJava.util.concurrent.atomic.AtomicLong; Public classThreadCount { Public Static voidMain (string[] args) {thread[] threads=Newthread[10000]; for(inti = 0; I < 10000; i++) {Threads[i]=NewAthread (); Threads[i].start (); } }}classAthreadextendsthread{@Override Public voidrun () {System.out.println (Mycounter.calnum ()); } }classcounter{Private Static Longnum; PublicCounter () {synchronized(Counter.class) {num++; } } Public Static synchronized LongCalnum () {returnnum; }}classmycounter{Private StaticAtomiclong num=NewAtomiclong (); Public static synchronized LongCalnum () {returnNum.incrementandget (); }}
In this case, when the counter is called, the new MyCounter object is not needed directly.
This allows you to call MyCounter's Calnum method directly as a tool class.