Sequential thread execution to print 1A 2B 3C 4D - java

I have implemented two threads, one to print integers and other one to print English alphabets. The threads are supposed to work in tandem.
I use a synchronized block and only one thread will hold the lock at a time. But somehow, the AtomicInteger is not working as expected. The changes to count variable made by one thread is not visible to other different thread. How's this possible. Am i missing something?
My Implementation
package com.concurrency;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadWaitEg
{
// Single monitor object for both threads
private final Object monitor = new Object();
// Thread-safe counter for both threads
private final AtomicInteger count = new AtomicInteger(0);
private class PrintNumber implements Runnable
{
#Override
public void run()
{
for (int i = 0; i < 26; i++)
{
synchronized (monitor)
{
System.out.println("From PrintNumber "+count.get());
try
{
while ((count.get()) % 2 != 0)
{
monitor.wait();
}
} catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(i);
count.getAndIncrement();
monitor.notifyAll();
}
}
}
}
private class PrintChar implements Runnable
{
#Override
public void run()
{
for (int charr = 'A'; charr <= 'Z'; charr++)
{
synchronized (monitor)
{
System.out.println("From PrintChar "+count.get());
try
{
while ((count.get()) % 2 == 0)
{
monitor.wait();
}
} catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println((char) charr);
count.getAndIncrement();
monitor.notifyAll();
}
}
}
}
public static void main(String[] args)
{
System.out.println("from main thread");
Runnable runInt = new ThreadWaitEg().new PrintNumber();
new Thread(runInt).start();
Runnable runChar = new ThreadWaitEg().new PrintChar();
new Thread(runChar).start();
System.out.println(" main thread completes ");
}
}
Output
from main thread
From PrintNumber 0
0
From PrintNumber 1
main thread completes
From PrintChar 0

Your main problem is that you create two instances of the main ThreadWaitEg class - each with its own copy of the "monitor" and "count" objects, thus the objects are not shared between the two threads. The quickest fix is to create just a single instance, i.e. replace you main() method with:
public static void main(String[] args) {
System.out.println("from main thread");
ThreadWaitEg threadWaitEg = new ThreadWaitEg();
Runnable runInt = threadWaitEg.new PrintNumber();
new Thread(runInt).start();
Runnable runChar = threadWaitEg.new PrintChar();
new Thread(runChar).start();
System.out.println(" main thread completes ");
}

Related

multithreading with loops inside the run() method

I have the following code to test multithreading. Inside the run() method, I have a loop. I instantiate my Runnable class and pass the object thus created to two different threads. My question is- How does the JVM deal with loop indexes ? Since a single Runnable object is passed to two different threads, won't it create confusion with loop indexes ?
public class ThreadTest1 implements Runnable{
public static void main(String[] args) {
ThreadTest1 tt = new ThreadTest1();
Thread t1 = new Thread(tt);
Thread t2 = new Thread(tt);
t1.start();
t2.start();
}
private synchronized void b() {
try {
for(int ii = 0; ii < 2; ii++) {
Thread.sleep(1000);
System.out.println("inside method 'b': " + this.toString() + " " + Thread.currentThread());
}
}
catch (InterruptedException e) {e.printStackTrace();}
}
#Override
public void run() {
this.b();
}
}

Semaphore with queue

public class SemaphoreWithQueues implements Semaphore {
private List<Object> queue;
private AtomicInteger current = new AtomicInteger(0);
private int permits;
public SemaphoreWithQueues(int permits) {
this.permits = permits;
this.queue = Collections.synchronizedList(new LinkedList<>());
}
#Override
public void enter() throws InterruptedException {
if (current.get() < permits) {
current.incrementAndGet();
} else {
Object block = new Object();
synchronized (block) {
queue.add(block);
block.wait();
current.incrementAndGet();
}
}
}
#Override
public void leave() {
if(queue.size() != 0) {
Object block = queue.get(0);
queue.remove(0);
synchronized (block) {
block.notify(); //Unblock quenue
}
}
current.decrementAndGet();
//current lessen and current thread have time come in block if(...)
// in enter() faster then another thread increased current
}
}
> The program usually output:
>
> 1 1 2 2 1 1 2 2 1 2
**Where run() of both threads is almost the same, such as:**
public void run(){
for (int i = 0; i <5; i++) {
try {
semaphore.enter();
} catch (InterruptedException e) {
System.err.println(e);
}
System.out.println(2);
semaphore.leave();
}
}
There are 2 threads using this semaphore. When 1 thread increases the queue, the second is waiting, the problem is that if we extracted the object from quene and unblocked it, then the thread that finished leave() start enter() faster and again increments the counter, while the awaked thread also increments the counter, current = 2, and the list is empty.
SORRY FOR BAD ENGLISH
There are many problems in the code.
Synchronization: Synchronization should be done for a shareable
resource. Why it is done for a local object which has scope only for
that method.
Object block = new Object();
synchronized (block) {
Both current and queue are independent properties, they should be
synchronized together.
Now let's come to point If you really want to create a semaphore using Queue. You do not need all this logic. You can use existing Java class e.g. BlockingQueue. Here is the implementation
class SemaphoreWithQueues implements Semaphore{
private BlockingQueue<Integer> queue;
public SemaphoreWithQueues(int permits) {
if(queue == null){
queue = new ArrayBlockingQueue<>(permits);
}
}
public void enter() {
queue.offer(1);
System.out.println(Thread.currentThread().getName() + " got a permit.");
}
public void leave() throws InterruptedException {
queue.take();
System.out.println(Thread.currentThread().getName() + " left the permit.");
}
}
And Task to use the semaphore
class Task implements Runnable {
private SemaphoreWithQueues semaphore;
public Task(SemaphoreWithQueues semaphore){
this.semaphore = semaphore;
}
public void run(){
for (int i = 0; i <5; i++) {
semaphore.enter();
try {
semaphore.leave();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
SemaphoreWithQueues semaphoreWithQueues = new SemaphoreWithQueues(5);
Thread th1 = new Thread(new Task(semaphoreWithQueues));
Thread th2 = new Thread(new Task(semaphoreWithQueues));
Thread th3 = new Thread(new Task(semaphoreWithQueues));
th1.start();
th2.start();
th3.start();
}
}
But personally I do not like using Queue to create Semaphores, as it wastes memory unnecessary by creating elements in queue. Despite of this you can create a semaphore using single shareable object with permits using wait and notify mechanism. You can try with this approach. If you would like.

printing alternative output from 2 threads using semaphores

I am learning about the use of semaphores and multi threading in general but am kind of stuck. I have two threads printing G and H respectively and my objective is to alternate the outputs of each thread so that the output string is like this;
G
H
G
H
G
H
Each of the two classes has a layout similar to the one below
public class ClassA extends Thread implements Runnable{
Semaphore semaphore = null;
public ClassA(Semaphore semaphore){
this.semaphore = semaphore;
}
public void run() {
while(true)
{
try{
semaphore.acquire();
for(int i=0; i<1000; i++){
System.out.println("F");
}
Thread.currentThread();
Thread.sleep(100);
}catch(Exception e)
{
System.out.println(e.toString());
}
semaphore.release();
}
}
}
below is my main class
public static void main(String[] args) throws InterruptedException {
Semaphore semaphore = new Semaphore(1);
ClassA clasA = new ClassA(semaphore);
Thread t1 = new Thread(clasA);
ClassB clasB = new ClassB(semaphore);
Thread t2 = new Thread(clasB);
t1.start();
t2.join();
t2.start();
The output I am getting is way too different from my expected result. can anyone help me please? did I misuse the semaphore? any help?
Semaphores can't help you solve such a task.
As far as I know, JVM doesn't promise any order in thread execution. It means that if you run several threads, one thread can execute several times in a row and have more processor time than any other. So, if you want your threads to execute in a particular order you can, for the simplest example, make a static boolean variable which will play a role of a switcher for your threads. Using wait() and notify() methods will be a better way, and Interface Condition will be the best way I suppose.
import java.io.IOException;
public class Solution {
public static boolean order;
public static void main(String[] args) throws IOException, InterruptedException {
Thread t1 = new ThreadPrint("G", true);
Thread t2 = new ThreadPrint("O", false);
t1.start();
t2.start();
t2.join();
System.out.println("Finish");
}
}
class ThreadPrint extends Thread {
private String line;
private boolean order;
public ThreadPrint(String line, boolean order) {
this.line = line;
this.order = order;
}
#Override
public void run() {
int z = 0;
while (true) {
try {
for (int i = 0; i < 10; i++) {
if (order == Solution.order) {
System.out.print(line + " ");
Solution.order = !order;
}
}
sleep(100);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}
BTW there can be another problem cause System.out is usually an Operation System buffer and your OS can output your messages in an order on its own.
P.S. You shouldn't inherit Thread and implement Runnable at the same time
public class ClassA extends Thread implements Runnable{
because Thread class already implements Runnable. You can choose only one way which will be better for your purposes.
You should start a thread then join to it not vice versa.
t1.start();
t2.join();
t2.start();
As others have pointed out, locks themselves do not enforce any order and on top of that, you cannot be certain when a thread starts (calling Thread.start() will start the thread at some point in the future, but this might take a while).
You can, however, use locks (like a Semaphore) to enforce an order. In this case, you can use two Semaphores to switch threads on and off (alternate). The two threads (or Runnables) do need to be aware of each other in advance - a more dynamic approach where threads can "join in" on the party would be more complex.
Below a runnable example class with repeatable results (always a good thing to have when testing multi-threading). I will leave it up to you to figure out why and how it works.
import java.util.concurrent.*;
public class AlternateSem implements Runnable {
static final CountDownLatch DONE_LATCH = new CountDownLatch(2);
static final int TIMEOUT_MS = 1000;
static final int MAX_LOOPS = 10;
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
try {
AlternateSem as1 = new AlternateSem(false);
AlternateSem as2 = new AlternateSem(true);
as1.setAlternate(as2);
as2.setAlternate(as1);
executor.execute(as1);
executor.execute(as2);
if (DONE_LATCH.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
System.out.println();
System.out.println("Done");
} else {
System.out.println("Timeout");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdownNow();
}
}
final Semaphore sem = new Semaphore(0);
final boolean odd;
AlternateSem other;
public AlternateSem(boolean odd) {
this.odd = odd;
}
void setAlternate(AlternateSem other) { this.other = other; }
void release() { sem.release(); }
void acquire() throws Exception { sem.acquire(); }
#Override
public void run() {
if (odd) {
other.release();
}
int i = 0;
try {
while (i < MAX_LOOPS) {
i++;
other.acquire();
System.out.print(odd ? "G " : "H ");
release();
}
} catch (Exception e) {
e.printStackTrace();
}
DONE_LATCH.countDown();
}
}

Threading in Sequence

I am trying to learn how to write a program which performs a given set of tasks in sequence with the help of threads. For example, Writing a program which have 3 different threads print 1111…, 22222…., 333333……, so that the output will be 1,2,3,1,2,3,1,2,3…..? OR for e.g. 2 threads one is printing odd numbers and other even numbers, but the output should be printed in sequence - i.e. one even and then odd.
I would like to learn how to write similar kind of programs in which different threads print different stuff concurrently and the output should be printed in sequence.
What is the basic concept in writing these programs. Can we use ThreadPools/Executors for the purpose ? For e.g. can we use
ExecutorService exectorService = Executors.newFixedThreadPool(3);
Can we use Future, FurtureTask, Callable, execute, submit ...? I know these concepts but I am not able to connect the dots for solving the above scenarios.
Please guide me how to go about writing these kind of programs using multithreading / concurrency.
I have written a program using wait()/notifyAll(). Following is the program. I am not executing the consumer as I am printing the whole sequence at the end. Also I am limiting the capacity of the queue to be 15. So I am basically printing the odd / even range till 15.
public class ProduceEven implements Runnable {
private final List<Integer> taskQueue;
private final int MAX_CAPACITY;
public ProduceEven (List<Integer> sharedQueue, int size) {
this.taskQueue = sharedQueue;
this.MAX_CAPACITY = size;
}
#Override
public void run() {
// TODO Auto-generated method stub
int counter = 0;
while (counter < 15) {
try {
produce(counter++);
} catch (InterruptedException e) {
e.getMessage();
}
}
}
private void produce (int i) throws InterruptedException {
synchronized (taskQueue) {
while (taskQueue.size() == MAX_CAPACITY) {
System.out.println("Queue is full : "+Thread.currentThread().getName()+" is waiting , size: "+ taskQueue.size());
taskQueue.wait();
}
Thread.sleep(1000);
if(i%2==0) {
taskQueue.add(i);
}
taskQueue.notifyAll();
}
}
}
public class ProduceOdd implements Runnable {
private final List<Integer> taskQueue;
private final int MAX_CAPACITY;
public ProduceOdd (List<Integer> sharedQueue, int size) {
this.taskQueue = sharedQueue;
this.MAX_CAPACITY = size;
}
#Override
public void run() {
int counter = 0;
while (counter < 15) {
try {
produce(counter++);
} catch (InterruptedException e) {
e.getMessage();
}
}
}
private void produce (int i) throws InterruptedException {
synchronized (taskQueue) {
while (taskQueue.size() == MAX_CAPACITY) {
System.out.println("Queue is full : "+Thread.currentThread().getName()+" is waiting , size: "+ taskQueue.size());
taskQueue.wait();
}
Thread.sleep(1000);
if(i%2==1) {
taskQueue.add(i);
}
taskQueue.notify();
}
}
}
public class OddEvenExampleWithWaitAndNotify {
public static void main(String[] args) {
List<Integer> taskQueue = new ArrayList<Integer>();
int MAX_CAPACITY = 15;
Thread tProducerEven = new Thread(new ProduceEven(taskQueue, MAX_CAPACITY), "Producer Even");
Thread tProducerOdd = new Thread(new ProduceOdd(taskQueue, MAX_CAPACITY), "Producer Odd");
tProducerEven.start();
tProducerOdd.start();
try {
tProducerEven.join();
tProducerOdd.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
ListIterator listIterator = taskQueue.listIterator();
System.out.println("Elements Are:: ");
while(listIterator.hasNext()) {
System.out.print(listIterator.next()+" ");
}
}
}
The output which I get is: Elements Are:: 02134657911810131214
The output is all jumbled up. Why is it not in sequence. 01234567891011121314 What am I missing. I would be now trying to make the program using Semaphores. Also how do we make this program using explicit locks?
Yes, you can use ExecutorService as a starting point to run your threads. You can also create and start your Threads manually, that would make no difference.
The important thing is that your Threads will run in parallel if you do not synchronize them (i.e., they have to wait for one another). To synchronize you can, e.g. use Semaphores or other thread communication mechanisms.
You wrote in the comments you have written a producer/consumer program. It's a bit of the same thing. Each time the 1-Thread produces a 1, the 2-Thread must know that it can now produce a 2. When it is finished, it must let the 3-Thread know that it must produce a 3. The basic concepts are the same. Just the threads have both producer and consumer roles.
Hi this is one sample program to print Odd and Even using two thread and using thread synchronization among them.
Also we have used Executor framework which is not mandatory, you can create thread using new Thread() as well. For quick prototype I have used system.exit() which can be replaced with graceful shutdown of threads like, interruption and all.
package com.ones.twos.threes;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class OnesTwos {
public static void main(String[] args) {
BlockingQueue<Integer> bq1 = new ArrayBlockingQueue<Integer>(100);
BlockingQueue<Integer> bq2 = new ArrayBlockingQueue<Integer>(100);
ExecutorService executorService = Executors.newFixedThreadPool(2);
try {
bq1.put(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.submit(new OddEven(bq1, bq2));
executorService.submit(new OddEven(bq2, bq1));
executorService.shutdown();
}
public static class OddEven implements Runnable {
BlockingQueue<Integer> bq1;
BlockingQueue<Integer> bq2;
public OddEven(BlockingQueue<Integer> bq1, BlockingQueue<Integer> bq2) {
this.bq1 = bq1;
this.bq2 = bq2;
}
#Override
public void run() {
while (true) {
try {
int take = bq1.take();
System.out.println(take);
bq2.offer(take + 1);
if (take > 20)
System.exit(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Mycode is also similar to Anirban's, except I am not using executor framework,
public class TestThread {
public static void main(String[] args) {
Boolean bol = new Boolean(true);
(new Thread(new Odd(bol), "odd")).start();
(new Thread(new Even(bol), "even")).start();
}
}
public class Even implements Runnable {
private Boolean flag;
public Even(Boolean b) {
this.flag = b;
}
#Override
public void run() {
for (int i = 2; i < 20; i = i + 2) {
synchronized (flag) {
try {
System.out.println(Thread.currentThread().getName()+":"+i);
Thread.sleep(1000);
flag.notify();
flag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Odd implements Runnable {
private Boolean flag;
public Odd(Boolean b) {
this.flag = b;
}
#Override
public void run() {
for (int i = 1; i < 20; i = i + 2) {
synchronized (flag) {
try {
System.out.println(Thread.currentThread().getName()+":"+i);
Thread.sleep(1000);
flag.notify();
flag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
By establishing the thread pool of 3 (ExecutorService exectorService = Executors.newFixedThreadPool(3); you are essentilly limiting the executor capacity to 3 and other incoming threads will be on hold. If you want to run them in paralel you can just submit them at once. If you want to wait for each other and want to find out the result I suggest you use Callable. Personally I really like Callable because after submiting it you can just call the get method of Future, wait for a returned value from the executed thread and then continue to the next one. From the API you can see this:
/**
* Submits a value-returning task for execution and returns a
* Future representing the pending results of the task. The
* Future's {#code get} method will return the task's result upon
* successful completion.
*
*
* If you would like to immediately block waiting
* for a task, you can use constructions of the form
* {#code result = exec.submit(aCallable).get();}
And a very good example here. If you go for the Callable alternative then you don't need a Thread pool. Just a normal executor is fine. Remember to shut the executor down in the end.
class MyNumber {
int i = 1;
}
class Task implements Runnable {
MyNumber myNumber;
int id;
Task(int id, MyNumber myNumber) {
this.id = id;
this.myNumber = myNumber;
}
#Override
public void run() {
while (true) {
synchronized (myNumber) {
while (myNumber.i != id) {
try {
myNumber.wait(); //Wait until Thread with correct next number
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(id);
if (myNumber.i == 1) {
myNumber.i = 2;
} else if (myNumber.i == 2) {
myNumber.i = 3;
} else {
myNumber.i = 1;
}
myNumber.notifyAll();
}
}
}
}
In main method:
MyNumber myNumber = new MyNumber();
new Thread(new Task(1, myNumber)).start();
new Thread(new Task(2, myNumber)).start();
new Thread(new Task(3, myNumber)).start();
Hi here we have used 2 thread one to print even and another to print odd.
Both are separate and have no relation to each other.
But we have to do a synchronization mechanism between them. Also we need a mechanism to let the ball rolling, i.e. start one thread printing.
Each thread is waiting on condition and after doing it's task it lets other thread work and put ownself in waiting state.
Well happy path works fine, but we need special care when even thread is not in waiting state and the signal() from main fires, in that case even thread will never able to wake up and the program hangs.
So to make sure main thread successfully sends a signal() to even thread and even thread does not miss that we have used Phaser(with party) and checking even thread state in while loop in main.
Code is as below.
package com.ones.twos.threes;
import java.util.concurrent.Phaser;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class OnesTwosTrial2 {
public static void main(String[] args) {
Lock lk = new ReentrantLock();
Phaser ph = new Phaser(3); // to let main start the even thread
Condition even = lk.newCondition();
Condition odd = lk.newCondition();
OnesTwosTrial2 onestwostrial2 = new OnesTwosTrial2();
Thread ev = onestwostrial2.new Evens(lk, even, odd, ph);
Thread od = onestwostrial2.new Odds(lk, even, odd, ph);
ev.start();
od.start();
System.out.println("in main before arrive");
ph.arriveAndAwaitAdvance();
System.out.println("in main after arrive");
// we have to make sure odd and even thread is
// started and waiting on respective condition.
// So we used Phaser with 3, because we are having here
// 3 parties (threads)
// main, odd,even. We will signal only when all the
// threads have started.
// and waiting on conditions.
while (!Thread.State.WAITING.equals(ev.getState())) {
System.out.println("waiting");
}
lk.lock();
even.signal();
lk.unlock();
}
class Evens extends Thread {
Lock lk;
Condition even;
Condition odd;
Phaser ph;
public Evens(Lock lk, Condition even, Condition odd, Phaser ph) {
this.lk = lk;
this.even = even;
this.odd = odd;
this.ph = ph;
}
#Override
public void run() {
System.out.println("even ph");
int cnt = 0;
while (cnt < 20) {
try {
lk.lock();
ph.arrive();
even.await();
System.out.println(cnt);
cnt += 2;
odd.signal();
lk.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Odds extends Thread {
Lock lk;
Condition even;
Condition odd;
Phaser ph;
public Odds(Lock lk, Condition even, Condition odd, Phaser ph) {
this.lk = lk;
this.even = even;
this.odd = odd;
this.ph = ph;
}
#Override
public void run() {
System.out.println("odd ph");
int cnt = 1;
while (cnt < 20) {
try {
lk.lock();
ph.arrive();
odd.await();
System.out.println(cnt);
cnt += 2;
even.signal();
lk.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

java synchronize multiple thread issue

I just write some code to test the multiple threads how to synchronize,but I cannot get my expected result.The code can start 3 threads,but only one thread to process the shared resource.what is wrong with my code.
class ThreadDemo1{
public static void main (String[] args){
MultiThread tt = new MultiThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
class MultiThread implements Runnable {
int tickets = 100;
Object _lock = new Object();
public void run () {
System.out.println(Thread.currentThread().getName());
synchronized(_lock) {
while (true) {
if (tickets>0) {
try {
Thread.sleep(10);
} catch (Exception e) {}
System.out.println(Thread.currentThread().getName() + " is selling "+tickets--);
}
}
}
}
}
You are sleeping while holding the lock. There is no reason to multithread if you are going to do that.
public void run () {
System.out.println(Thread.currentThread().getName());
while(tickets > 0) {
synchronized(_lock) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + tickets--);
}
}
try {
Thread.sleep(10);
} catch (Exception e) {
}
}
}
I'm guessing the sleep was a placeholder for your processing. If possible, you should do the check and decrement inside the synchronized block, but your lengthy processing outside it.
In order for locks and multi-threading to do anything useful for you, you must make sure that your synchronized code takes as little time as possible, since that is the code that can be run by only one thread at a time.
In your code, the only thing that wasn't effectively single-threaded was your first System.println.
FYI, with that in mind, if you could have your print statements accurate but possibly out of order, it would be even better to have:
public void run () {
System.out.println(Thread.currentThread().getName());
while(tickets > 0) {
int oldTickets = 0;
synchronized(_lock) {
if (tickets > 0) {
oldTickets = tickets--;
}
}
if(oldTickets > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + oldTickets);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
}
[1]First, there are several bad practice/mistakes in your posted code:
(1) It's better that the Lock Object to be singleton. You can use an static field object or the Class itself(Since there is only one Class in memory)
Object _lock = new Object();
private static final Object _lock = new Object();
(2) Put the while(true) {...} out of the synchronized block. In your code, if the 1st thread obtains the Lock, it will process ALL the tickets and will not stop.
Should make every thread try to obtain the Lock in each iteration of the loop.
(3) For the Thread.sleep(10), I guess you mean the thread is doing some heavy job. But it's not a good practice to put this kind of code in synchronized block(Or another name: critical region). Because there is only one thread can access the synchronized block at one time. The behavior of you code is like a single thread program, because other threads must wait until the currently running thread finishes its job.
Pls see below code:
public class ThreadDemo1 {
public static void main(String[] args) {
MultiThread tt = new MultiThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
public class MultiThread implements Runnable {
private static int tickets = 100;
private static final Object _lock = new Object();
public void run() {
System.out.println(Thread.currentThread().getName());
while (tickets > 0) {
try {
synchronized (_lock) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + tickets--);
}
}
Thread.sleep(10);
} catch (Exception e) {
}
}
}
}
[2]Second, if you just want to synchronize the threads in picking the tickets. Try to use Atomic* Classes instead of synchronized block, it’s No-lock and will bring you a better performance. Example:
import java.util.concurrent.atomic.AtomicInteger;
public class MultiThreadAtomic implements Runnable {
private static AtomicInteger tickets = new AtomicInteger(100);
public void run() {
System.out.println(Thread.currentThread().getName());
int ticketsRemaining = 0;
while ((ticketsRemaining = tickets.getAndDecrement()) > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + ticketsRemaining);
try {
Thread.sleep(10);
}
catch(InterruptedException ie) {}
}
}
}

Categories

Resources