I'd like to set parameter on Runnable then get value.
I wrote this code. When I run this code return [2, 3, 3]. Because the thread share temp_value.
Then I added sleep which was comment outed. The result is [1, 2, 3]. It works fine!! But.. it is not real multithread, right?
Even it's running multithread, but I need wait the each process finish for the shared value.
How can solve this problem?
import java.util.ArrayList;
public class Foo implements Runnable {
private int temp_value;
private ArrayList<Integer> values = new ArrayList<Integer>();
private ArrayList<Integer> newValues = new ArrayList<Integer>();
public Foo(ArrayList<Integer> values) {
this.values = values;
}
public static void main(String[] args) {
// make initial values
ArrayList<Integer> values = new ArrayList<Integer>();
values.add(1);
values.add(2);
values.add(3);
// set values then process and get new values
Foo foo = new Foo(values);
foo.startAppendValue(foo);
System.out.println(foo.getNewValues());
}
public void startAppendValue(Foo foo) {
Thread thread = null;
int max = values.size();
for (int i = 0; i < max; i++) {
foo.temp_value =foo.values.get(i);
thread = new Thread(foo);
thread.start();
// try {
// Thread.sleep(10);
// } catch (Exception e) {
// // TODO: handle exception
// }
}
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void run() {
newValues.add(temp_value);
}
public ArrayList<Integer> getNewValues() {
return this.newValues;
}
}
You can use Callable and ExecutorService to do the stuff
public class MyCallable implements Callable<Integer> { //Callable is like Runnable but can return value
private Integer value;
public MyCallable(Integer v) {
value = v;
}
public Integer call() {
return value;
}
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(3); //Creating thread pool with 3 worker threads
List<Integer> values = Arrays.asList(1, 2, 3);
List<Future<Integer>> futures = new ArrayList<>(values.size());
List<Integer> newValues = new ArrayList<>(values.size());
for (Integer v : values) {
futures.add(exec.submit(new MyCallable(v))); //Submit tasks to worker threads to do stuff in background
}
for (Future<Integer> f : futures) {
try {
newValues.add(f.get()); // get calculated result from worker thread or block waiting for result to become available
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
System.out.println(newValues);
exec.shutdownNow();
}
}
I would use a List.parallelStream()
public class Foo {
public static void main(String[] args) {
// make initial values
List<Integer> values = new ArrayList<Integer>();
values.add(1);
values.add(2);
values.add(3);
// process each value using multiple threads.
List<Integer> results = values.parallelStream()
.map(Foo::processValue)
.collect(Collectors.toList());
}
static Integer processValue(Integer i) {
// do something interesting
return i;
}
}
Even it's running multithread, but I need wait the each process finish for the shared value.
Correct, you need to make sure.
each thread has it's only copy of the data.
shared collections are accessed in a thread safe manner.
I tried writing this with Threads but it's far too painful to post here.
i think your shared data makes mistake. for this keep i in private space. you can have class like this:
remove temp_value from Foo class and move runnable part to new class named PV.
Class PV implements Runnable{
int index;
Foo foo;
PV(int index,Foo foo){
this.index = index;
this.foo = foo;
}
}
#Override
public void run() {
this.foo.newValues.add(foo.values.get(index));
}
}
PV[] pvArr = new PV[max];
for (int i = 0; i < max; i++) {
pvArr[i] = new PV(i,foo);
foo.temp_value =foo.values.get(i);
thread = new Thread(pvArr[i]);
thread.start();
Related
public class ClassTest extends Thread{
public static Object lock = new Object();
public static LinkedList<Integer> stack;
public SortedSet<Integer> set= new TreeSet<>();
#Override
public void run(){
synchronized(lock){
// try{
// this.wait();
// }
// catch(Exception e){
// e.printStackTrace();
// }
while(!stack.isEmpty()){
set.add(stack.pop());
this.yield();
// this.notifyAll();
}
}
}
When i start() 5 Threads why just first one pop all elements and others do not pop anyone?
I tried to use wait() and notify() methods, but that didn't help..
The method yield does not release locks. The very first thread that enters the synchronized block will keep other threads from entering until the stack is empty and the lock is released.
Here is an example that does what you want using LinkedBlockingDeque.
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.LinkedBlockingDeque;
class Main {
static final LinkedBlockingDeque<Integer> stack = new LinkedBlockingDeque<>();
static class Poller implements Runnable {
final Set<Integer> set = new HashSet<>();
#Override
public void run() {
Integer elem = stack.poll();
while (elem != null) {
set.add(elem);
System.out.printf("%s: %d\n", Thread.currentThread().getName(), elem);
elem = stack.poll();
}
}
}
public static void main(String args[]) {
for (int i = 0; i < 100; i++) {
stack.push(i);
}
for (int i = 0; i < 5; i++) {
new Thread(new Poller()).start();
}
}
}
I have a TreeSet with a comparator:
private final TreeSet<TimedTask> sortedEvents;
public TimedUpdatableTaskList(){
Comparator<TimedTask> comparator = new TimedTaskComparator();
sortedEvents = new TreeSet<>(comparator);
}
The class implements a method to add elements to the set:
public void add(TimedTask task) {
synchronized (sortedEvents) {
sortedEvents.add(task);
log.info("Add task {}:{}", task.getClass().getName(), task);
}
}
The TimedTasks added are like this:
class AIRepairTask extends TimedTask {
private AsyncEventBus clientServerEventBus;
private final IShip ship;
private final IShipyard shipyard;
public AIRepairTask(LocalDateTime executionTime, IShip ship, IShipyard shipyard) {
super();
setExecutionTime(executionTime);
this.ship = ship;
this.shipyard = shipyard;
}
#Override
public void run() {
ship.repair();
shipyard.removeCompletedRepair(ship);
ship.setAvailable(true);
clientServerEventBus.post(new RepairFinishedEvent(ship));
}
}
And then there is a method that iterates over the elements and eventually removes them:
public void handleClockTick(ClockTick event) {
LocalDateTime now = date.getCurrentDate();
int nbHandledTasks = 0;
synchronized (sortedEvents) {
int initialSize = sortedEvents.size();
boolean moreEvents = true;
while(moreEvents && !sortedEvents.isEmpty()) {
TimedTask task = sortedEvents.first();
Preconditions.checkNotNull(task.getExecutionTime(), "The exectution time of the task may not be null");
if (task.getExecutionTime().isBefore(now)) {
try {
task.run();
boolean removed = sortedEvents.remove(task);
Preconditions.checkArgument(removed, "The Task "+task+" was not removed.");
nbHandledTasks++;
} catch (Exception e) {
e.printStackTrace()
}
} else {
moreEvents = false;
}
}
Preconditions.checkArgument(initialSize - nbHandledTasks == sortedEvents.size(), "List size did not become smaller: initial size "+initialSize+", handled tasks "+nbHandledTasks+", actual list size: "+sortedEvents.size());
}
}
As the essential parts are wrapped in a synchronized block, the set should not change while iterating over the elements.
Given that there are no exceptions in the try block, the precondition check at the end, should never fail, but that is exactly what happens:
java.lang.IllegalArgumentException: List size did not become smaller: initial size 41, handled tasks 2, actual list size: 41
How can this happen?
I have a program where 3 Threads are trying to print numbers in sequence from 1 to 10. I am using a CountDownLatch to keep keep a count.
But the program stops just after printing 1.
Note: I am aware that using AtomicInteger instead of Integer can work. But I am looking to find out the issue in the current code.
public class Worker implements Runnable {
private int id;
private volatile Integer count;
private CountDownLatch latch;
public Worker(int id, Integer count, CountDownLatch latch) {
this.id = id;
this.count = count;
this.latch = latch;
}
#Override
public void run() {
while (count <= 10) {
synchronized (latch) {
if (count % 3 == id) {
System.out.println("Thread: " + id + ":" + count);
count++;
latch.countDown();
}
}
}
}
}
Main program:
public class ThreadSequence {
private static CountDownLatch latch = new CountDownLatch(10);
private volatile static Integer count = 0;
public static void main(String[] args) {
Thread t1 = new Thread(new Worker(0, count, latch));
Thread t2 = new Thread(new Worker(1, count, latch));
Thread t3 = new Thread(new Worker(2, count, latch));
t1.start();
t2.start();
t3.start();
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Edited program with AtomicInteger:
public class ThreadSequence {
private static AtomicInteger atomicInteger = new AtomicInteger(1);
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new WorkerThread(0, atomicInteger));
Thread t2 = new Thread(new WorkerThread(1, atomicInteger));
Thread t3 = new Thread(new WorkerThread(2, atomicInteger));
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
System.out.println("Done with main");
}
}
public class WorkerThread implements Runnable {
private int id;
private AtomicInteger atomicInteger;
public WorkerThread(int id, AtomicInteger atomicInteger) {
this.id = id;
this.atomicInteger = atomicInteger;
}
#Override
public void run() {
while (atomicInteger.get() < 10) {
synchronized (atomicInteger) {
if (atomicInteger.get() % 3 == id) {
System.out.println("Thread:" + id + " = " + atomicInteger);
atomicInteger.incrementAndGet();
}
}
}
}
}
But the program stops just after printing 1.
No this is not what happens. None of the threads terminate.
You have a own count field in every worker. Other threads do not write to this field.
Therefore there is only one thread, where if (count % 3 == id) { yields true, which is the one with id = 0. Also this is the only thread that ever modifies the count field and modifying it causes (count % 3 == id) to yield false in subsequent loop iterations, causing an infinite loop in all 3 threads.
Change count to static to fix this.
Edit
In contrast to Integer AtomicInteger is mutable. It is a class that holds a int value that can be modified. Using Integer every modification of the field replaces it's value, but using AtomicInteger you only modify the value inside the AtomicInteger object, but all 3 threads continue using the same AtomicInteger instance.
Your "count" is a different variable for each thread, so changing it in one thread doesn't affect the rest, and so they are all waiting for it to change, without any one that can do it.
Keep the count as static member in Worker class - common for all object in the class.
You can use below code to print sequential numbers using multiple threads -
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ThreadCall extends Thread {
private BlockingQueue<Integer> bq = new ArrayBlockingQueue<Integer>(10);
private ThreadCall next;
public void setNext(ThreadCall t) {
this.next = t;
}
public void addElBQ(int a) {
this.bq.add(a);
}
public ThreadCall(String name) {
this.setName(name);
}
#Override
public void run() {
int x = 0;
while(true) {
try {
x = 0;
x = bq.take();
if (x!=0) {
System.out.println(Thread.currentThread().getName() + " =>" + x);
if (x >= 100) System.exit(0); // Need to stop all running threads
next.addElBQ(x+1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int THREAD_COUNT = 10;
List<ThreadCall> listThread = new ArrayList<>();
for (int i=1; i<=THREAD_COUNT; i++) {
listThread.add(new ThreadCall("Thread " + i));
}
for (int i = 0; i < listThread.size(); i++) {
if (i == listThread.size()-1) {
listThread.get(i).setNext(listThread.get(0));
}
else listThread.get(i).setNext(listThread.get(i+1));
}
listThread.get(0).addElBQ(1);
for (int i = 0; i < listThread.size(); i++) {
listThread.get(i).start();
}
}
}
I hope this will resolve your problem
How can I make the following method return a character array ?
public char[] startThread() {
// arr declaration
Runnable r = new Runnable() {
#Override
public void run() {
arr = getArray(); // arr assignment
}
};
new Thread(r).start();
return arr;
}
char arrNew[] = startThread();
Note : The above snippet generates an error
Look for java.util.concurrent.Callable, its similar to runnable but returns a value.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Callable.html
or
If in 1.6 JDK, you can look for Future objects.
You cannot do that.
When you return from your method, you don't have your char array. It is not created yet. So, assigning as a reference will not work. Neither Callable will help on this.
What you can do is that you create a holder object, and return that (this is very similar to Future objects):
public static class ArrayHolder {
public char[] arr;
}
public ArrayHolder startThread() {
final ArrayHolder holder = new ArrayHolder();
Runnable r = new Runnable() {
#Override
public void run() {
holder.arr = getArray(); // arr assignment
}
};
new Thread(r).start();
return holder;
}
ArrayHolder h = startThread();
char arrNew[] = h.arr;
Notice, that h.arr will change in time, so the first time you call it it will most likely return null
Generally, as java developers all know that we must use "synchronized" to control the method execution one by one, but I see the following code choose static variable to control, and i can't simulate the condition to demonstrate that the method is error, how do I modify the code to output the value more than 1000?
public class ThreadJunk implements Runnable{
private Info info;
public ThreadJunk(Info info) {
this.info = info;
}
public static void main(String args[]) throws Exception {
for(int j=0;j<100;j++) {
Info ii = new Info();
for(int i=0;i<1000;i++) {
Thread t = new Thread(new ThreadJunk(ii));
t.start();
}
System.out.println(ii.getValue());
}
}
#Override
public void run() {
info.addValue();
}
}
class Info {
public static boolean IS_LOCKED = false;
private int value = 0;
public void addValue() {
if(IS_LOCKED)
return;
IS_LOCKED = true;
value++;
IS_LOCKED = false;
}
public int getValue() {
return value;
}
}
In my computer, I have never get the result that more than 1000
Look at this part of your code:
Info ii = new Info();
for (int i = 0; i < 1000; i++) {
Thread t = new Thread(new ThreadJunk(ii));
t.start();
}
For every Info object you are creating no more than 1000 threads. You should not expect the value field to get incremented more than 1000 times.
Info object has value as member variable.And one Info object is shared in 999 threads as per your thread creation logic.
for(int j=0;j<100;j++) {
Info ii = new Info();
for(int i=0;i<1000;i++) {
Thread t = new Thread(new ThreadJunk(ii));
t.start();
}
System.out.println(ii.getValue());
}
Hence obviously following would be never greater than 1000.
System.out.println(ii.getValue())