I've been testing to write multiple items to a filesystem, fully expecting to get a failure where by one thread overwrites anthers data, or interleaves with the data from another item.
However the following code unexpectedly passes.
Why is the data from one thread not overwriting the data from another thread? All the threads share one writer. Does the code pass because of a JVM implementation detail, or can it genuinely be expected to not mix up individual items.
I've seen some other quests about multiple threads writing to the same file but these were about performance optimizations. Note the import style is just for brevity when posting.
package com.test;
import static org.junit.Assert.assertEquals;
import java.io.*;
import java.nio.charset.*;
import java.nio.file.*;
import java.util.*;
import org.springframework.boot.CommandLineRunner;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.ObjectMapper;
public class DiskWriterApplication implements CommandLineRunner {
public static void main(String[] args) throws Exception {
new DiskWriterApplication().run(args);
}
#Override
public void run(String... args) throws Exception {
Path path = Paths.get(System.getProperty("user.home")+"/java-file.txt");
if (!Files.exists(path)) {
Files.createFile(path);
} else {
Files.delete(path);
Files.createFile(path);
}
BufferedWriter writer = Files.newBufferedWriter(path, Charset.forName("UTF-8"), StandardOpenOption.APPEND);
Thread[] threads = new Thread[4];
for (int i=0; i< 4; i++) {
threads[i] = new Thread(new DataWriter(writer, createDataItems(i)));
}
Arrays.asList(threads).forEach(Thread::start);
Arrays.asList(threads).forEach(t-> {
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
writer.close();
//Verify Lines were written correctly
ObjectMapper mapper = new ObjectMapper();
MappingIterator<Data> valueIterator = mapper.readerFor(Data.class).readValues(Files.newInputStream(path));
Set<String> uniqueItems = new HashSet<>();
int[] groupItemCount = new int[4];
while (valueIterator.hasNext())
{
Data item = valueIterator.next();
assertEquals("First Item and second Item should be equal", item.firstValue, item.secondValue);
assertEquals(10, item.innerObject.size());
assertEquals(20, item.listValues.size());
for (int i = 0 ; i< 10; i++) {
assertEquals(item.firstValue, item.innerObject.get("innerProp"+i));
}
for (int i = 0 ; i< 20; i++) {
assertEquals(item.firstValue, item.listValues.get(i));
}
uniqueItems.add(item.firstValue);
groupItemCount[item.group]++;
}
System.out.println("Got " + uniqueItems.size() + " uniqueItems");
assertEquals("Should be 4000 uniqueItems", 4000, uniqueItems.size());
assertEquals("Should be 1000 items in group[0]", 1000, groupItemCount[0]);
assertEquals("Should be 1000 items in group[1]", 1000, groupItemCount[1]);
assertEquals("Should be 1000 items in group[2]", 1000, groupItemCount[2]);
assertEquals("Should be 1000 items in group[3]", 1000, groupItemCount[3]);
}
private List<Data> createDataItems(int groupNumber) {
List<Data> items = new ArrayList<>();
for (int i =0; i<1000; i++) {
Data item = new Data();
item.group = groupNumber;
item.itemNumber = i;
item.firstValue = "{group" + groupNumber + "item" + i + "}";
item.secondValue = "{group" + groupNumber + "item" + i + "}";
for (int j =0; j< 10; j ++) {
item.addInnerProperty("innerProp"+j , "{group" + groupNumber + "item" + i + "}");
}
for (int j=0; j<20; j++) {
item.addListValue("{group" + groupNumber + "item" + i + "}");
}
items.add(item);
}
return items;
}
private class DataWriter implements Runnable {
private ArrayList<String> data;
private PrintWriter writer;
public DataWriter(BufferedWriter writer, List<Data> items) {
this.writer = new PrintWriter(writer);
this.data = new ArrayList<String>();
ObjectMapper mapper = new ObjectMapper();
for (Data i : items) {
try {
String stringValue = mapper.writeValueAsString(i);
data.add(stringValue);
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
#Override
public void run() {
System.out.println("Starting batch");
data.forEach(t -> {
writer.println(t);
writer.flush();
});
System.out.println("finishing batch");
}
}
public static class Data {
public int itemNumber;
public int group;
#JsonProperty
private String firstValue;
#JsonProperty
private String secondValue;
#JsonProperty
private Map<String, String> innerObject = new HashMap<>();
#JsonProperty
private List<String> listValues = new ArrayList<>();
public void addInnerProperty(String key, String value){
this.innerObject.put(key, value);
}
public void addListValue(String value) {
this.listValues.add(value);
}
}
}
As you can see in the others threads asking the same thing :
Writing a file using multiple threads in java
Is writting on file using bufferwriter initialized by filewriter thread safe or not?
the BufferedWriter is synchronized and thread-safe
I am using Fork join pool in java for multitasking. Now i came across a situation where, for every task, I need to hit a url then wait for 10 minutes and then again hit another url to read the data. Now the problem is that for those 10 minutes my CPU is idle and not starting another tasks ( more than those defined in fork join pool).
static ForkJoinPool pool = new ForkJoinPool(10);
public static void main(String[] args){
List<String> list = new ArrayList<>();
for(int i=1; i<=100; i++){
list.add("Str"+i);
}
final Tasker task = new Tasker(list);
pool.invoke(task);
public class Tasker extends RecursiveAction{
private static final long serialVersionUID = 1L;
List<String> myList;
public Tasker(List<String> checkersList) {
super();
this.myList = checkersList;
}
#Override
protected void compute() {
if(myList.size()==1){
System.out.println(myList.get(0) + "start");
//Date start = new Date();
try {
Thread.sleep(10*60*1000);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(myList.get(0) + "Finished");
}
else{
List<String> temp = new ArrayList<>();
temp.add( myList.get( myList.size()-1 ) );
myList.remove( myList.size()-1 );
Tasker left = new Tasker(myList);
Tasker right = new Tasker(temp);
left.fork();
right.compute();
left.join();
}
}
Now What should I do so that CPU picks all the tasks and then wait parallaly for them.
Unfortunately, ForkJoinPool does not work well in the face of Thread.sleep(), because it designed for many short tasks that finish quickly, rather than tasks that block for a long time.
Instead, for what you are trying to accomplish, I would recommend using ScheduledThreadPoolExecutor and dividing your task into two parts.
import java.util.*;
import java.util.concurrent.*;
public class Main {
static ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(10);
public static void main(String[] args){
for(int i=1; i<=100; i++){
pool.schedule(new FirstHalf("Str"+i), 0, TimeUnit.NANOSECONDS);
}
}
static class FirstHalf implements Runnable {
String name;
public FirstHalf(String name) {
this.name = name;
}
public void run() {
System.out.println(name + "start");
pool.schedule(new SecondHalf(name), 10, TimeUnit.MINUTES);
}
}
static class SecondHalf implements Runnable {
String name;
public SecondHalf(String name) {
this.name = name;
}
public void run() {
System.out.println(name + "Finished");
}
}
}
If Java provides a thread pool which allows releasing the underlying resources (that is, the kernel thread participating in the thread pool) during a Thread.sleep(), you should use that instead, but I currently do not know of one.
According to docs forkJoin basic use section tells:
if (my portion of the work is small enough)
do the work directly
else
split my work into two pieces
invoke the two pieces and wait for the results
Hopefully this meets your need if you are using forkjoin
public class Tasker extends RecursiveAction {
static ForkJoinPool pool = new ForkJoinPool(10);
static int threshold = 10;
public static void main(String[] args){
List<String> list = new ArrayList<>();
for(int i=1; i<=100; i++){
list.add("Str"+i);
}
final Tasker task = new Tasker(list);
pool.invoke(task);
}
private static final long serialVersionUID = 1L;
List<String> myList;
public Tasker(List<String> checkersList) {
super();
this.myList = checkersList;
}
void computeDirectly() {
for(String url : myList){
System.out.println(url + " start");
}
//Date start = new Date();
try {
//keep hitting url
while (true) {
for(String url : myList) {
//url hitting code here
System.out.println(url + " hitting");
}
Thread.sleep(10 * 60 * 1000);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(String url : myList){
System.out.println(url + " Finished");
}
}
#Override
protected void compute() {
if (myList.size() <= threshold) {
computeDirectly();
return;
}
//temp list have only one url
//List<String> temp = new ArrayList<>();
//temp.add( myList.get( myList.size()-1 ) );
//myList.remove( myList.size()-1 );
//Tasker left = new Tasker(myList);
//Tasker right = new Tasker(temp);
//left.fork();
//right.compute();
//left.join();
List<String> first = new ArrayList<>();
List<String> second = new ArrayList<>();
//divide list
int len = myList.size();
int smHalf = len / 2;//smaller half
first = myList.subList(0, smHalf);
second = myList.subList(smHalf + 1, len);
invokeAll(new Tasker(first), new Tasker(second));
}
}
Here is what I am trying to do. I have a number of threads which should all wait at a common point before they proceed, so obvious solution is to use CyclicBarrier. But I want to also compute the total time taken by the threads to execute. I defined the following utility method in class ConcurrentExecutionActionTimer.
public static long elapsedTimeUsingCyclicBarrier(Executor executor, int concurrency, final Runnable action) throws InterruptedException
{
final Runnable barrierAction = new Runnable() {
#Override
public void run() {
System.out.println("Condition of barrier is met.");
}
};
final
CyclicBarrier barrier = new CyclicBarrier(concurrency, barrierAction);
final CountDownLatch done = new CountDownLatch(concurrency);
for(int i=0; i<concurrency; i++ ){
executor.execute(new Runnable() {
#Override
public void run() {
try {
System.out.println("Waiting at barrier.");
barrier.await();
action.run();
//Cyclic barrier gets reset automatically. Again wait for them to finish.
barrier.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (BrokenBarrierException e) {
e.printStackTrace();
} finally {
done.countDown();
}
}
});
}
long startNanoTime = System.nanoTime();
done.await();
return System.nanoTime() - startNanoTime;
}
Then I called it up like:
public static void main(String[] args) {
//Executor is replacement for common thread idiom: (new Thread(r)).start() to e.execute(r)
ExecutorService executor = Executors.newFixedThreadPool(10);
Worker action = new Worker();
int concurrency = 5;
try {
long elapsedTime = ConcurrentExecutionActionTimer.elapsedTimeUsingCyclicBarrier(executor, concurrency, action);
double seconds = (double)elapsedTime / 1000000000.0;
System.out.println("Time Taken approximately: " + seconds + "seconds.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Here Worker is suppose my thread that does some work. For example:
class Worker implements Runnable {
#Override
public void run() {
System.out.println("Doing work.");
for(int i=0; i<20; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Finished.");
}
}
As I wanted to print the time taken I had to use CountDownLatch to make sure the control does not return back to main before all the threads are finished. Do we have any other way to make sure the same functionality?
You should use the same CyclicBarrier instance. The only difference is that you make the cyclic barrier count be #threads + 1. You can then use that barrier to calculate the time it took all of the threads to complete. The start time is calculated when the first barrier has been reached and the end time is calculated when the second barrier has been reached. This way you know approximately when all the threads have been started and when all of them have completed.
Therefore this:
long startNanoTime = System.nanoTime();
done.await();
return System.nanoTime() - startNanoTime;
becomes:
barrier.await()
long startNanoTime = System.nanoTime();
barrier.await();
return System.nanoTime() - startNanoTime;
import java.io.*;
import java.util.*;
import java.util.concurrent.CyclicBarrier;
class BusLine {
private String destination;
protected static int max_seat, checkpoint;
private ArrayList<Bus> BUSA = new ArrayList<Bus>();
private ArrayList<Bus> BUSC = new ArrayList<Bus>();
private ArrayList<Group> GROUP_A = new ArrayList<Group>();
private ArrayList<Group> GROUP_C = new ArrayList<Group>();
public BusLine(int ms, int cp, String d) {
max_seat = ms;
checkpoint = cp;
destination = d;
}
public String getDestination() {
return destination;
}
public void printAirportCheckpoint() {
System.out.println();
System.out.printf("%s >> %d airport-bound buses have been allocated.", Thread.currentThread().getName(), BUSA.size());
}
public void printCityCheckpoint() {
System.out.println();
System.out.printf("%s >> %d city-bound buses have been allocated.", Thread.currentThread().getName(), BUSC.size());
System.out.println();
System.out.println();
}
public void BusBoundA() {
int temp = 0;
for (int i = 0; i < BUSA.size(); i++) {
if (BUSA.get(i).getName().equals("A" + i)) {
temp++;
}
}
System.out.println();
System.out.printf("%s >> ==== Airport Bound ====", Thread.currentThread().getName());
System.out.println();
for (int i = 0; i < temp; i++) {
System.out.printf("%s >> %s : ", Thread.currentThread().getName(), "A" + i);
for (int j = 0; j < GROUP_A.size(); j++) {
if (GROUP_A.get(j).getBusname().equals("A" + i)) {
System.out.printf(" %-20s(%2d seats)", GROUP_A.get(j).getName(), GROUP_A.get(j).getSeat());
//System.out.printf(",");
}
} System.out.println();
}
}
public void BusBoundC() {
int temp = 0;
for (int i = 0; i < BUSC.size(); i++) {
if (BUSC.get(i).getName().equals("C" + i)) {
temp++;
}
}
System.out.println();
System.out.printf("%s >> ==== City Bound ====", Thread.currentThread().getName());
System.out.println();
for (int i = 0; i < temp; i++) {
System.out.printf("%s >> %s : ", Thread.currentThread().getName(), "C" + i);
for (int j = 0; j < GROUP_C.size(); j++) {
if (GROUP_C.get(j).getBusname().equals("C" + i)) {
System.out.printf(" %-20s(%2d seats)", GROUP_C.get(j).getName(), GROUP_C.get(j).getSeat());
//System.out.printf(",");
}
} System.out.println();
}
}
synchronized public void allocateBus(Data d) {
TicketCounter T = (TicketCounter) (Thread.currentThread());
while (d.getSeat() != 0) {
if ("A".equals(d.getDestination())) {
if (BUSA.size() == 0 || BUSA.get(BUSA.size() - 1).getAvailableSeat() == 0) {
BUSA.add(new Bus("A" + BUSA.size()));
}
if (d.getSeat() <= BUSA.get(BUSA.size() - 1).getAvailableSeat()) {
System.out.printf("%s >> Transaction %2d : %-20s(%2d seats) bus %s\n", T.getName(), d.getTransaction(), d.getName(), d.getSeat(), BUSA.get(BUSA.size() - 1).getName());
GROUP_A.add(new Group(BUSA.get(BUSA.size() - 1).getName(), d.getName(), d.getSeat()));
BUSA.get(BUSA.size() - 1).Bookingseat(d.getSeat());
d.finishedBooking(d.getSeat());
} else {
System.out.printf("%s >> Transaction %2d : %-20s(%2d seats) bus %s\n", T.getName(), d.getTransaction(), d.getName(), BUSA.get(BUSA.size() - 1).getAvailableSeat(), BUSA.get(BUSA.size() - 1).getName());
GROUP_A.add(new Group(BUSA.get(BUSA.size() - 1).getName(), d.getName(), BUSA.get(BUSA.size() - 1).getAvailableSeat()));
d.finishedBooking(BUSA.get(BUSA.size() - 1).getAvailableSeat());
BUSA.get(BUSA.size() - 1).Bookingseat(BUSA.get(BUSA.size() - 1).getAvailableSeat());
}
} else {
if (BUSC.size() == 0 || BUSC.get(BUSC.size() - 1).getAvailableSeat() == 0) {
BUSC.add(new Bus("C" + BUSC.size()));
}
if (d.getSeat() <= BUSC.get(BUSC.size() - 1).getAvailableSeat()) {
System.out.printf("%s >> Transaction %2d : %-20s(%2d seats) bus %s\n", T.getName(), d.getTransaction(), d.getName(), d.getSeat(), BUSC.get(BUSC.size() - 1).getName());
GROUP_C.add(new Group(BUSC.get(BUSC.size() - 1).getName(), d.getName(), d.getSeat()));
BUSC.get(BUSC.size() - 1).Bookingseat(d.getSeat());
d.finishedBooking(d.getSeat());
} else {
System.out.printf("%s >> Transaction %2d : %-20s(%2d seats) bus %s\n", T.getName(), d.getTransaction(), d.getName(), BUSC.get(BUSC.size() - 1).getAvailableSeat(), BUSC.get(BUSC.size() - 1).getName());
GROUP_C.add(new Group(BUSC.get(BUSC.size() - 1).getName(), d.getName(), BUSC.get(BUSC.size() - 1).getAvailableSeat()));
d.finishedBooking(BUSC.get(BUSC.size() - 1).getAvailableSeat());
BUSC.get(BUSC.size() - 1).Bookingseat(BUSC.get(BUSC.size() - 1).getAvailableSeat());
}
}
}
}
}
class Group {
private String busname, name;
private int seat;
public Group(String n, String b, int s) {
busname = n;
name = b;
seat = s;
}
public String getName() { return name; }
public String getBusname() { return busname; }
public int getSeat() { return seat; }
}
class Bus {
private String Busname, group_name;
private int availableseat, seat;
public int getAvailableSeat() { return availableseat; }
public String getName() { return Busname; }
public void Bookingseat(int s) { availableseat -= s; }
public String getGroupname() { return group_name; }
public Bus(String n) {
availableseat = BusLine.max_seat;
Busname = n;
}
public Bus(String n, int s) {
group_name = n;
seat = s;
}
public Bus(String n, String gn, int s) {
Busname = n;
group_name = gn;
availableseat = s;
}
}
class Data {
private String name, destination;
private int seat, transaction, count = 0;
public int getCount() { return count; }
public int getTransaction() { return transaction; }
public String getName() { return name; }
public int getSeat() { return seat; }
public String getDestination() { return destination; }
public void finishedBooking(int s) { seat -= s; }
public Data(int t, String n, int s, String d) {
transaction = t;
name = n;
seat = s;
destination = d;
}
}
class TicketCounter extends Thread {
ArrayList<Data> transaction;
BusLine Airport, City;
private CyclicBarrier cfinish;
public void setCyclicBarrier(CyclicBarrier f) {
cfinish = f;
}
public TicketCounter(String n, ArrayList<Data> d, BusLine a, BusLine c) {
super(n);
transaction = d;
Airport = a;
City = c;
}
public void run() {
for (int i = 0; i < transaction.size(); i++) {
if (transaction.get(i).getTransaction() == BusLine.checkpoint) {
try {
cfinish.await();
cfinish.await();
} catch (Exception e) {}
}
if ("A".equals(transaction.get(i).getDestination())) {
Airport.allocateBus(transaction.get(i));
} else {
City.allocateBus(transaction.get(i));
}
}
}
}
class Userinput {
private ArrayList<Data> DATA1 = new ArrayList<Data>();
private ArrayList<Data> DATA2 = new ArrayList<Data>();
private ArrayList<Data> DATA3 = new ArrayList<Data>();
public Userinput() {}
public ArrayList<Data> getDATA1() { return DATA1; }
public ArrayList<Data> getDATA2() { return DATA2; }
public ArrayList<Data> getDATA3() { return DATA3; }
public void input() {
String infile[] = {"T1.txt", "T2.txt", "T3.txt"};
for (int i = 0; i < 3; i++) {
boolean opensuccess = false;
while (!opensuccess) {
try ( Scanner scanfile = new Scanner(new File(infile[i]));) {
while (scanfile.hasNext()) {
opensuccess = true;
String line = scanfile.nextLine();
String[] buf = line.split(",");
int transaction = Integer.parseInt(buf[0].trim());
String name = buf[1].trim();
int seat = Integer.parseInt(buf[2].trim());
String destination = buf[3].trim();
Data d = new Data(transaction, name, seat, destination);
switch (i) {
case 0: DATA1.add(d);
break;
case 1: DATA2.add(d);
break;
case 2: DATA3.add(d);
break;
}
}
} catch (FileNotFoundException e) {
System.out.println(e);
Scanner scan = new Scanner(System.in);
System.out.println("Enter new file name : ");
infile[i] = scan.nextLine();
}
}
}
}
}
public class Simulation {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
Thread Th = Thread.currentThread();
System.out.printf("%s >> Enter max seats = ", Th.getName());
System.out.println();
int max_seat = scan.nextInt();
System.out.printf("%s >> Enter checkpoints = ", Th.getName());
System.out.println();
int checkpoint = scan.nextInt();
Userinput U = new Userinput();
BusLine Airport = new BusLine(max_seat, checkpoint, "A");
BusLine City = new BusLine(max_seat, checkpoint, "C");
CyclicBarrier CB = new CyclicBarrier(4);
U.input();
TicketCounter[] T = {
new TicketCounter("T1", U.getDATA1(), Airport, City),
new TicketCounter("T2", U.getDATA2(), Airport, City),
new TicketCounter("T3", U.getDATA3(), Airport, City)};
for (int i = 0; i < 3; i++) {
T[i].setCyclicBarrier(CB);
T[i].start();
}
try {
CB.await();
Airport.printAirportCheckpoint();
City.printCityCheckpoint();
CB.await();
}catch (Exception e){}
for (int i = 0; i < 3; i++) {
try {
T[i].join();
} catch (Exception e) {
System.err.println(e);
}
}
Airport.BusBoundA();
City.BusBoundC();
}
}
I tried to convert the Getting-started Akka tutorial from Scala to Java and replace actors with threads.
The tutorial can be found here http://typesafe.com/resources/tutorials/getting-started-with-akka-scala.html
The original Pi.scala file can be checked out from Typesafe giter8 template repository
g8 typesafehub/akka-first-tutorial-scala
I would like to know if what I did is correct.
And this is my Pi.java
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class Pi {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Listener listener = new Listener();
//calculate(nrOfWorkers = 10, nrOfElements = 10000, nrOfMessages = 10000)
Master master = new Master(4, 1000, 1000, listener);
master.calculate();
}
}
class Worker implements Callable<Double> {
private int start;
private int nrOfElements;
public Worker(int start, int nrOfElements) {
this.start = start;
this.nrOfElements = nrOfElements;
}
#Override
public Double call() throws Exception {
double acc = 0.0;
for(int i = start; i < start + nrOfElements; i++) {
acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1);
}
return acc;
}
}
class Listener {
public void PiApproximation(double pi, long duration) {
System.out.println(String.format("\n\tPi approximation: \t\t%s\n\tCalculation time: \t%s", pi, duration));
}
}
class Master {
private double pi = 0.0;
private int nrOfResults = 0;
private final long start = java.lang.System.currentTimeMillis();
private int nrOfWorkers;
private int nrOfMessages;
private int nrOfElements;
private Listener listener;
private ExecutorService executor;
public Master(int nrOfWorkers,
int nrOfMessages,
int nrOfElements,
Listener listener) {
this.nrOfWorkers = nrOfWorkers;
this.nrOfMessages = nrOfMessages;
this.nrOfElements = nrOfElements;
this.listener = listener;
//Round robin scheduling is not enforced here as in akka.
executor = Executors.newFixedThreadPool(nrOfWorkers);
}
public void calculate() {
List<Future<Double>> list = new ArrayList<Future<Double>>();
for (int i = 0; i < nrOfMessages; i++) {
Callable<Double> worker = new Worker(i * nrOfElements, nrOfElements);
Future<Double> submit = executor.submit(worker);
list.add(submit);
}
for (Future<Double> future : list) {
try {
pi += future.get();
}
catch (InterruptedException e) { e.printStackTrace(); }
catch (ExecutionException e) { e.printStackTrace(); }
}
//send results to listener
listener.PiApproximation(pi, java.lang.System.currentTimeMillis() - start);
executor.shutdown();
}
}
There is a java version of this tutorial online also:
http://doc.akka.io/docs/akka/2.0.1/intro/getting-started-first-java.html
However, it is NOT using Threads, it is using Actors in java.
Why would you want to use Threads instad of Actors?
I have a program that creates a queue, enqueues objects to the queue and then dequeues them one by one if the queue is not empty. The problem I am having is that the queue comes up empty each time it is checked. Print is called on the queue after enqueuing each object and it prints the queue's contents just fine.
import java.util.*;
import java.io.*;
public class Processor2
{
private LinkedQueue queue = new LinkedQueue();
private int time = 0;
private int count = 100;
private int amount = 0;
private PrintWriter out;
private Person temp;
private boolean var;
private Random randomNum = new Random();;
private String turn;
private int popCount=0;
private int loopCount =0;
public void start()
{
amount = randomNum.nextInt(5);
amount += 5;
pop(amount, time);
sim();
}
public void pop(int num, int time)
{
for(int i=1; i<=num; i++)
{
Person pe = new Person(i, time, 0);
queue.enqueue(pe);
System.out.println(queue);
}
popCount += num;
}
public void sim()
{
try
{
out = new PrintWriter(new FileWriter("output.txt"));
while(loopCount<=100)
{
var = queue.isEmpty();
if(var=true)
{
System.out.println("queue is empty");
}
if(var=false)
{
Object temp = queue.dequeue();
double rand = Math.random();
if(rand < 0.5)
{
System.out.println("inside if else statement");
// does stuff with object //
loopCount++;
}
else
{
System.out.println("inside if else statement");
// does stuff with object //
loopCount++;
}
}
}
out.close();
}
catch (IOException ioe)
{
System.out.println("Error Writing to File: " + ioe);
}
}
}
there doesn't seem to be anything wrong with the queue's isEmpty() method, but here it is:
public boolean isEmpty()
{
if(count == 0)
{
return true;
}
else
{
return false;
}
}
var = queue.isEmpty();
if(var=true) // this line *sets* var to true
{
System.out.println("queue is empty");
}
If you change if (var=true) to if(var==true) or just if(var) you should see a different result