ExecutorService slower than sequential file process of copying file - java

This is my code for copying file from one directory to other using ExecutorService but it turned out to be slower than sequential operation. Am using apache FileUtils copyFile method which is not synchronized. What's the problem?
public class ExecutorService {
private static java.util.concurrent.ExecutorService pool;
public ExecutorService() {
pool = Executors.newFixedThreadPool(20);
}
public static void main(String arg[]) {
long a = System.currentTimeMillis();
new ExecutorService();
List<File> listFiles = null;
try {
listFiles = FileUtility.getFileNamesToExtract(new File(
"C:/Users/User/Desktop/XSLT Source/Input XML"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 0; i < listFiles.size(); i++)
pool.submit(new FileTransfer(listFiles.get(i), i));
pool.shutdown();
try {
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long b = System.currentTimeMillis();
System.out.println((b - a) / 1000);
}
}
public class FileTransfer implements Runnable{
private File file = null;
private int num = 0;
public FileTransfer(File file, int i) {
this.file = file;
this.num = i;
}
#Override
public void run() {
try {
System.out.println("Processing="+file.getName());
FileUtils.copyFile(file, new File("C:/Users/gursahibsahni/Desktop/thread pool files/"+num+"_"+file.getName()+num));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

What's the problem?
I can't really see why you would think a thread pool can speed up file transfer. Try this: run your single-threaded version and monitor CPU usage. My expectation: it will be below 10%.
File copying is not a CPU-intensive operation and moreover, parallelizing it only means you create a difficult disk access pattern, which slows down the whole thing and probably also causes more file fragmentation.

Related

Replacing Future<Integer> with Future<Void>

I am writing an application that searches for Java files in a given directory and its subdirectories and writes all the strings from those files in reverse order to a new folder. Each directory and file is handled in a separate thread.
At the moment my program works correctly, but I want to change its behavior.
Right now, the program overwrites the files correctly and outputs the number of overwritten files to the console at the end. I want my program to just overwrite the files and display the line "All files overwritten" at the end. But I don't quite understand how I can change my code and replace Future (I think that's my problem). Here is part of the code from the Main class:
ExecutorService pool = Executors.newCachedThreadPool();
ReverseWritter reverseWritter = new ReverseWritter(dirToSearch, dirToStorePath + "//" + dirToStoreName, pool);
Future<Integer> res = pool.submit(reverseWritter);
try {
System.out.println(res.get() + " files reversed");
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
pool.shutdown();
Here's the method that overwrites the file:
public boolean reverseWrite(File file) {
if (file.isFile() && file.toString().endsWith(".java")) {
String whereTo = dirToStorePathName + "\\" + file.getName().substring(0, file.getName().indexOf(".java")) + "Reversed" + ".java";
try ( Scanner myReader = new Scanner(file); FileWriter myWriter = new FileWriter(whereTo);) {
while (myReader.hasNextLine()) {
String data = myReader.nextLine();
myWriter.write(new StringBuffer(data).reverse().toString());
myWriter.write(System.getProperty("line.separator"));
}
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
return false;
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
return false;
}
}
return true;
}
And this is the call method (my class implements the Callable interface):
#Override
public Integer call() {
int count = 0;
try {
File[] files = dirToSearch.listFiles();
ArrayList<Future<Integer>> result = new ArrayList<>();
for (File f : files) {
if (f.isDirectory()) {
ReverseWritter reverseWritter = new ReverseWritter(f, dirToStorePathName, pool);
Future<Integer> rez = pool.submit(reverseWritter);
result.add(rez);
} else if (reverseWrite(f)) {
count++;
}
for (Future<Integer> rez : result) {
count += rez.get();
}
}
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
return count;
}
You just need to change the class to implement Callable<Void> and remove the operations which do the counting. Change the return type of call from Integer to Void.
public class ReverseWriterCallable implements Callable<Void> {
#Override
public Void call() throws Exception {
//do stuff
//don't do the counting operations
//when return type is Void you can only return null
return null;
}
}
Or implement Runnable and submit it to the executor service.
public class ReverseWriterRunnable implements Runnable {
#Override
public void run() {
//do stuff
//don't do the counting operations
}
}
Then just don't care about the result of the Future:
try {
res.get();
System.out.println("All files reversed");
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
pool.shutdown();

Have 3 threads running...only receiving info from last thread....new at threads

I have 3 rfid readers where I am reading rfid tags. I am running those but for some reason I am only receiving info from the last reader(thread) that is being processed. What am I missing? The readers are in an array containing the ipaddress, username, port, password. Can I listen on the same service for all of them? I'm new to threads........TagInventory is the name of the class where all of this is located.
Here is the code:
private void Start() throws AlienReaderException, IOException{
ThreadStop = false;
service= new MessageListenerService(3900);
service.setMessageListener(this);
service.startService();
System.out.println("length of readers: "+Reader.ipAddress.length);
for (lastThreadId = 0; lastThreadId < Reader.ipAddress.length; lastThreadId++)
{
m_inventory[lastThreadId] = new AlienReader(Reader.ipAddress[lastThreadId], Reader.port, Reader.username[lastThreadId], Reader.password[lastThreadId]);
log.info("taginventory reader: "+ Reader.ipAddress[lastThreadId]+"Thread: "+lastThreadId);
m_run_process[lastThreadId] = new Thread(new StartInventoryThread(Reader.ipAddress[lastThreadId], Reader.port, Reader.username[lastThreadId], Reader.password[lastThreadId], m_inventory[lastThreadId]));
m_run_process[lastThreadId].start();
}
--lastThreadId;
try
{
// Thread.sleep(1000);
Thread.sleep(2000);
}
catch (Exception ex)
{
ex.getMessage();
}
}
class StartInventoryThread implements Runnable{
private String ip;
private int port;
private String user;
private String pwd;
private AlienReader ar;
StartInventoryThread(String ip, int port, String user, String pwd, AlienReader ar){
this.ip=ip;
this.port=port;
this.user=user;
this.pwd=pwd;
this.ar=ar;
}
#Override
public void run() {
try {
while(!stopInventory){
startRead(ip,port,user,pwd);
}
} catch (AlienReaderException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void startRead(String ip, int port, String user, String password) throws AlienReaderException, InterruptedException, UnknownHostException{
String myIP=InetAddress.getLocalHost().getHostAddress();
//System.out.println("ip"+ ip);
AlienReader ar= new AlienReader(ip, port, user, password);
ar.open();
//log.info("Reader" + ar.getIPAddress());
ar.setNotifyAddress(myIP, 3900);
ar.setNotifyFormat(AlienClass1Reader.TEXT_FORMAT);
//ar.setNotifyTrigger("TrueFalse");
ar.setNotifyTrigger("Add");
ar.setNotifyMode(AlienClass1Reader.ON);
// log.info("MessageListenerService has started for reader: " + ip);
//complete process in here
ar.autoModeReset();
ar.setAutoStopTimer(5000); // Read for 5 seconds
ar.setAutoMode(AlienClass1Reader.ON);
tagTable.setTagTableListener(tagTableListener);
tagTable.setPersistTime(3600);
//tagTable.setPersistTime(1800000);
ar.close();
long runTime = 10000; // milliseconds
long startTime = System.currentTimeMillis();
do {
Thread.sleep(1000);
} while(service.isRunning()
&& (System.currentTimeMillis()-startTime) < runTime);
// Reconnect to the reader and turn off AutoMode and TagStreamMode.
// log.info("\nResetting Reader");
ar.open();
ar.autoModeReset();
ar.setNotifyMode(AlienClass1Reader.OFF);
ar.close();
}
public static void main(String args[]){
Thread thr=new Thread(new Runnable(){
#Override
public void run(){
try {
new TagInventory();
} catch (AlienReaderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
thr.start();
}
Overview
I see a number of issues and potential hazards in your logic throughout the code. I will step through each and guide you to the corresponding concepts that align with these issues.
Main
In your main(String args[]), add a join() call so that the calling thread (likely the main thread) can wait until Thread thr finishes before exiting.
public static void main(String args[]){
Thread thr=new Thread(new Runnable(){
#Override
public void run(){
try {
new TagInventory();
} catch (AlienReaderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
thr.start();
thr.join();
}
Start
Assuming you are expecting the threads to finish by the time the Start() function finishes I will explain how to obtain that functionality. Do not utilize Thread.sleep() as it is considered poor programming. Instead utilize the join() function. The forces the calling thread to wait or block until that thread has finished. The logic added below will cycle through each of the m_run_process and block until it has finished. If you have another location where you want to ensure they all finish, you can put the for-loop there instead.
private void Start() throws AlienReaderException, IOException{
ThreadStop = false;
service= new MessageListenerService(3900);
service.setMessageListener(this);
service.startService();
System.out.println("length of readers: "+Reader.ipAddress.length);
for (lastThreadId = 0; lastThreadId < Reader.ipAddress.length; lastThreadId++)
{
m_inventory[lastThreadId] = new AlienReader(Reader.ipAddress[lastThreadId], Reader.port, Reader.username[lastThreadId], Reader.password[lastThreadId]);
log.info("taginventory reader: "+ Reader.ipAddress[lastThreadId]+"Thread: "+lastThreadId);
m_run_process[lastThreadId] = new Thread(new StartInventoryThread(Reader.ipAddress[lastThreadId], Reader.port, Reader.username[lastThreadId], Reader.password[lastThreadId], m_inventory[lastThreadId]));
m_run_process[lastThreadId].start();
}
--lastThreadId;
for(Thread inventoryThread : m_run_process)
inventoryThread.join()
}
StartRead
There seems to be a lot of problems here where you are accesses non-thread-safe objects and variables; service, stopInventory, and tagTable (without seeing the full file I am making assumptions and I do not see synchronization anywhere). Now, I recommend reading up on the Java Memory Model, Java Memory Barrier, Atomic Operations, Synchronization, Thread-Safety, and the JVM. In essence, your logic can cause overwriting of data and/or threads see different caches values. To rectify you must make shared, mutable instances thread-safe through synchronization and atomicity.
public void startRead(String ip, int port, String user, String password) throws AlienReaderException, InterruptedException, UnknownHostException{
String myIP=InetAddress.getLocalHost().getHostAddress();
//System.out.println("ip"+ ip);
AlienReader ar= new AlienReader(ip, port, user, password);
ar.open();
//log.info("Reader" + ar.getIPAddress());
ar.setNotifyAddress(myIP, 3900);
ar.setNotifyFormat(AlienClass1Reader.TEXT_FORMAT);
//ar.setNotifyTrigger("TrueFalse");
ar.setNotifyTrigger("Add");
ar.setNotifyMode(AlienClass1Reader.ON);
// log.info("MessageListenerService has started for reader: " + ip);
//complete process in here
ar.autoModeReset();
ar.setAutoStopTimer(5000); // Read for 5 seconds
ar.setAutoMode(AlienClass1Reader.ON);
tagTable.setTagTableListener(tagTableListener);
tagTable.setPersistTime(3600);
//tagTable.setPersistTime(1800000);
ar.close();
long runTime = 10000; // milliseconds
long startTime = System.currentTimeMillis();
do {
Thread.sleep(1000);
} while(service.isRunning()
&& (System.currentTimeMillis()-startTime) < runTime);
// Reconnect to the reader and turn off AutoMode and TagStreamMode.
// log.info("\nResetting Reader");
ar.open();
ar.autoModeReset();
ar.setNotifyMode(AlienClass1Reader.OFF);
ar.close();
}

How to handle third-party Java code in a Task submitted to ExecutorService in case it has an infinite loop

Let's say I have a third-party Java library called in a Task submitted to ExecutorService.
I trust the third-party library to not be malicious, but there is a rare chance that there are programming errors that can cause it to get stuck in an infinite loop, and if this is the case, I cannot fix it to address those rare occasions.
What is the best way to handle this so that the application doesn't get stuck as well? Is shutdownNow() good enough to handle this situation?
There's a related issue Stop an infinite loop in an ExecutorService task but this relies on the ability of the programmer to be cooperative and detect Thread.currentThread().isInterrupted() to stop processing, which I can't rely on.
(In my case it's Jython code; in an early version of Jython the interpreter apparently didn't check Thread.currentThread().isInterrupted(), not sure what it does now... but my question is general for any 3rd-party Java code.)
If the task has an infinite loop that does not check for the thread interrupted status and does not use methods that throw InterruptedExceptions, it won't be stopped by shutdownNow().
Simple example that doesn't allow you program to finish:
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(1);
e.submit(() -> { while (true); });
e.shutdownNow();
System.out.println("Main is finished but the app keeps running");
}
One way would be to run the thread as a daemon:
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(1, r -> {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
});
e.submit(() -> { while (true); });
e.shutdownNow();
System.out.println("Main is finished and the app can exit");
}
Following my correct reading of the question I put together this set of classes. Relatively simple: One Runnable that connects to a socket sending input and retrieving output from a secondary jvm that invokes the erratic library.
If after 3 tries no response has been received the secondary jvm is killed. But it could be relaunched. The secondary jvm has an exit hook to close down sockets.
class SafetyValve implements Runnable{
PrintWriter out;
BufferedReader in;
Socket s = null;
AtomicBoolean flag;
SafetyValve(AtomicBoolean b){
flag = b;
}
#Override
public void run() {
try {
s = new Socket("localhost", 9000);
out = new PrintWriter(s.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
while (!Thread.currentThread().isInterrupted()){
flag.set(false);
out.print(0);
out.flush();
System.out.print(in.read());
flag.set(true);
}
} catch (Exception e) {
e.printStackTrace();
}
finally{
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Main/Controller class. It uses a Thread class for control
public class Switch {
public static void main(String[] args) {
try {
AtomicBoolean flag = new AtomicBoolean(false);
int counter = 0;
ProcessBuilder pb = ...
pb.directory(,,,);
Process p = pb.start();
SafetyValve sv = new SafetyValve(flag);
Thread t = new Thread(sv);
t.start();
while(t.getState() != Thread.State.RUNNABLE){
Thread.sleep(10);
}
while(true){
if (flag.get() == false){
if (++counter == 3){
while(t.getState() != Thread.State.TERMINATED){
p.destroyForcibly();
t.interrupt();
Thread.sleep(10);
}
break;
}
}
else
counter = 0;
Thread.sleep(100);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The secondary jvm has an standard server socket implementation:
class UnYielding{
int i = 0;
int returnInt(){
i++;
if (i > 2)
while(true);
return i;
}
}
class Hook extends Thread{
RunWild rw;
Hook(RunWild wr){
rw = wr;
}
public void run() {
try {
System.out.println("exit...");
System.out.flush();
rw.socket.close();
rw.server.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class RunWild {
ServerSocket server;
Socket socket;
RunWild(){
Runtime.getRuntime().addShutdownHook(new Hook(this));
}
public static void main(String[] args){
UnYielding u;
int i;
PrintWriter out;
BufferedReader in;
RunWild rw = new RunWild();
try {
rw.server = new ServerSocket(9000);
rw.socket = rw.server.accept();
out = new PrintWriter(rw.socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(rw.socket.getInputStream()));
u = new UnYielding();
while ((i = in.read()) != -1){
out.print(u.returnInt());
out.flush();
Thread.sleep(10);
System.out.print("waiting...");
System.out.flush();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I have tested this against 1.8 on OS X it works as expected. If this unstable classes are needed this is one way of doing it

Why hasn't the PriorityBlockingQueue queue to sort elements according to the priority

This my code ,the code run the end is not my excepted.
I think the PriorityBlockingQueue sorted by Priority but the end is not my expected,Who can told me why.
public class TestPriorityQueue {
static Random r=new Random(47);
public static void main(String args[]) throws InterruptedException{
final PriorityBlockingQueue q=new PriorityBlockingQueue();
ExecutorService se=Executors.newCachedThreadPool();
//execute producer
se.execute(new Runnable(){
public void run() {
int i=0;
while(true){
q.put(new PriorityEntity(r.nextInt(10),i++));
try {
TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
//execute consumer
se.execute(new Runnable(){
public void run() {
while(true){
try {
System.out.println("take== "+q.take()+" left:== ["+q.toString()+"]");
try {
TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("shutdown");
}
}
class PriorityEntity implements Comparable<PriorityEntity> {
private static int count=0;
private int id=count++;
private int priority;
private int index=0;
public PriorityEntity(int priority,int index) {
this.priority = priority;
this.index=index;
}
public String toString(){
return id+"* [index="+index+" priority="+priority+"]";
}
//数字大,优先级高
public int compareTo(PriorityEntity o) {
return this.priority < o.priority ? 1
: this.priority > o.priority ? -1 : 0;
}
}
The following are the results,I would be very grateful to you for your help
Some observations:
in most cases the size of your queue was 1. Clearly, no sort order is relevant in any of those.
In a few cases the queue size may have been two, and in no such case does the output insinuate that an element of lower priority was preferred. I stress the verb "insinuate" because...
your code has no synchronized blocks so nothing prevents the following sequence of operations:
q.take(); // consumer thread
q.put(); // producer thread
q.toString(); // consumer thread
with the legitimate outcome of q.toString() showing an element of higher priority than was taken.

Java Future. It suceeds in debug mode but fails when i run it normally

Guys I'm facing a similar situation
like
This junit case on another thread
though i don't have a junit case. I tried everything that i know of.. including suggestion on that link page, keeping a countdown and thread sleep but the results don't change. if i run through debug and give it some time it shows me all the results from all the thread but if i run it normally it invariably gives me less results.
My code is as belows
`
AtomicInteger atomicInteger = new AtomicInteger(employeeids.size());
CountDownLatch latch = new CountDownLatch(employeeids.size());
Iterable<List<String>> batchList = createBatches(employeeids, batchSize);
Set<Future<List<GradeSearchDTO>>> set = new HashSet<Future<List<GradeSearchDTO>>>();
for(List<String> employeeidsList: batchList) {
Callable<List<GradeSearchDTO>> callable = new ScheduleCallable( employeetype, employeedetails, employeeidsList, dept, seeker, atomicInteger,latch );
Future<List<GradeSearchDTO>> future = pool.submit(callable);
set.add(future);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
latch.await(getTimeOutInMillis(), TimeUnit.MILLISECONDS);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
throw new EmployeeException("Building of Schedules didn't finish in time of ["+getTimeOutInMillis()+"] millis. ");
}
long timeLeft = getTimeOutInMillis();
boolean check=true;
while (check){
logger.debug("Waiting for building asset. countdown value is[" + timeLeft+"]");
try {
Thread.sleep(TIME_TO_PAUSE);
timeLeft = timeLeft - TIME_TO_PAUSE;
if(timeLeft == 0 || timeLeft < 0){
throw new EmployeeException("Building of Schedules didn't finish in time of ["+getTimeOutInMillis()+"] millis. ");
}
for (Future<List<GradeSearchDTO>> future : set) {
if(!future.isDone()){
check=true;
break;
}
else{check=false;}
}
} catch (InterruptedException e) {
logger.error("Error waiting for asset to build to bulid");
}
}
for (Future<List<GradeSearchDTO>> future : set) {
try {
EmployeeScheduleList.addAll(future.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static class ScheduleCallable implements Callable
{
private String employeetype;
private List<Employee> employeedetails;
private List<String> employeeidsList;
private String dept;
private EmployeeSeekerHelper seeker;
private AtomicInteger atomicInteger;
private CountDownLatch latch;
public ScheduleCallable(String employeetype,List<Employee> employeedetails,
list<String> employeeidsList, String dept,EmployeeSeekerHelper seeker,AtomicInteger
atomicInteger,CountDownLatch latch )
{
this.employeetype = employeetype;
this.employeedetails = employeedetails;
this.employeeidsList = employeeidsList;
this.dept = dept;
this.seeker = seeker;
this.atomicInteger=atomicInteger;
this.latch=latch;
}
public List<GradeSearchDTO> call()
{
List<GradeSearchDTO> EmployeeScheduleList = new ArrayList<GradeSearchDTO>(0) ;
int counter=1;
for(String scheduleId : employeeidsList)
{
latch.countDown();
EmployeeScheduleList.addAll(searchEmployeeRulesForSchedule(employeetype,employeedetails,scheduleId,dept,seeker,latch));
System.out.println("Thread COUNTER "+counter);
atomicInteger.decrementAndGet();
counter++;
// latch.countDown();
}
return EmployeeScheduleList;
}
}
`
So the above code is perfectly fine... nothing wrong at all. The problem that i faced with the random results was because the method searchEmployeeRulesForSchedule(employeetype,employeedetails,scheduleId,dept,seeker,latch)
which does the business logic under the call() was internally calling a rules engine which was not returning proper results because of the usage of same instance of a class instead of a new instance for each thread.

Categories

Resources