Java-a method of orderly execution of multithreads

Keywords: Java

My colleagues inadvertently raised this question and personally practiced two methods. There are certainly more and better ways. If you know, please leave a message to me. If there is something wrong in the article, please let me know. Thank you.~

Method 1

import java.util.concurrent.atomic.AtomicInteger;

public class OrderedThread1 {
	
	static AtomicInteger count = new AtomicInteger(0);

	public static void main(String[] args) throws InterruptedException {
		Task task1 = new Task(count, 0);
		Task task2 = new Task(count, 1);
		Task task3 = new Task(count, 2);
		Thread thread1 = new Thread(task1);
		Thread thread2 = new Thread(task2);
		Thread thread3 = new Thread(task3);
		thread1.setDaemon(true);
		thread2.setDaemon(true);
		thread3.setDaemon(true);
		thread1.start();
		thread2.start();
		thread3.start();
		
		Thread.sleep(1 * 1000);
	}

}

class Task implements Runnable {
	
	private AtomicInteger count;
	private int order;
	
	public Task(AtomicInteger count, int order) {
		this.count = count;
		this.order = order;
	}

	@Override
	public void run() {
		while (true) {
			if (count.get() % 3 == order) {
				System.out.println(Thread.currentThread().getName() + "  =====  "+ order);
				count.incrementAndGet();
			}
		}
	}
}

This method should be a common solution. Thread access sequence is controlled by atomic increment.

Method two

public class OrderedThread2 {
	static Holder holder = new Holder();
	public static void main(String[] args) throws InterruptedException {
		
		Task1 task1 = new Task1(holder, 0);
		Task1 task2 = new Task1(holder, 1);
		Task1 task3 = new Task1(holder, 2);
		Thread thread1 = new Thread(task1);
		Thread thread2 = new Thread(task2);
		Thread thread3 = new Thread(task3);
		thread1.setDaemon(true);
		thread2.setDaemon(true);
		thread3.setDaemon(true);
		thread1.start();
		thread2.start();
		thread3.start();
		
		Thread.sleep(1 * 1000);
		

	}

}

class Task1 implements Runnable {
	
	Holder holder;
	int order;
	
	public Task1(Holder holder, int order) {
		this.holder = holder;
		this.order = order;
	}

	@Override
	public void run() {
		while (true) {
			if (holder.count % 3 == order) {
				System.out.println(Thread.currentThread().getName() + "  =====  "+ order);
				holder.count ++;
			}
		}
//		int i = 0;
//		while(i ++ < 10000){
//			holder.count ++;
//		}
	}
}
class Holder {
	volatile int count = 0;
}

Method 2 uses volatile keyword. Let each thread get the latest count value. When one thread performs the + + operation, the other two threads get the latest value and check whether they meet the admission requirements.

ps: volatile is not thread-safe. And they have nothing to do with each other. Volatile variables do not save copies in user threads, so all threads can provide the latest values. But imagine that if multiple threads update this variable concurrently, the result is also obvious, the last update will cover all previous updates, resulting in thread insecurity. In method 2, only one thread satisfies the admission requirement at a time, so there is no concurrent update of variables. Volatile values are up-to-date and completely unrelated to thread security, so don't misuse volatile for concurrency control.

Posted by seany123 on Sun, 21 Apr 2019 12:42:34 -0700