What I want to do here is to print even numbers by even consumers, odd numbers by odd consumers.
There is an evenodd method which is basically consuming any number and printing (whether even or odd). I have got 2 even consumer threads, 2 odd consumer threads, 2 evenodd consumer threads and 3 producer threads.
I am new to the semaphores concept, and I tried using it. When I remove the evenodd method and related threads I get the correct output i.e. Even numbers by even threads and odd numbers by odd threads. But when I again put the evenodd method and evenodd threads I get a deadlock.
It would be very helpful if anyone can guide me on this, where I am going wrong and how to fix it. Please throw some light on how I can implement the evenodd method so that it would work correctly.
package lab61;
import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class Process {
Semaphore empty;
Semaphore full;
Semaphore even;
Semaphore odd;
Semaphore mutex;
//Semaphore evenodd;
boolean evenb;
boolean oddb,eo;
LinkedList<Integer> list;
Random random;
public Process(int capacity){
list=new LinkedList<Integer>();
empty=new Semaphore(capacity);
full=new Semaphore(0,true);
mutex=new Semaphore(1,true);
even=new Semaphore(0,true);
evenb=false;
oddb=false;
eo=false;
odd=new Semaphore(0,true);
//evenodd = new Semaphore(0,true);
random=new Random();
}
public void Producer() throws InterruptedException{
while(true){
int a=random.nextInt(100);
empty.acquire();
mutex.acquire();
list.add(a);
System.out.println("Producing "+a);
System.out.println(list);
if((list.get(0)%2)==0){
if(!evenb){
even.release();
evenb = true;
}
}else if((list.get(0)%2)==1){
if(!oddb){
odd.release();
oddb = true;
}
}
/*if(((list.get(0)%2)==0)||((list.get(0)%2)==1)){
if(!eo){
evenodd.release();
eo = true;
}
}*/
mutex.release();
full.release();
}
}
public void consumereven() throws InterruptedException{
while(true){
//Thread.sleep(2000);
even.acquire();
Thread.sleep(2000);
full.acquire();
mutex.acquire();
int value = list.removeFirst();
System.out.println("I am the even consumer "+ value);
evenb = false;
System.out.println(list);
mutex.release();
empty.release();
}
}
public void consumerodd() throws InterruptedException{
while(true){
//Thread.sleep(2000);
odd.acquire();
Thread.sleep(2000);
full.acquire();
//odd.acquire();
mutex.acquire();
int value = list.removeFirst();
System.out.println("I am the odd consumer "+ value);
System.out.println(list);
oddb = false;
mutex.release();
empty.release();
}
}
public void evenodd() throws InterruptedException {
while(true){
full.acquire();
mutex.acquire();
int value = list.removeFirst();
System.out.println("i am the evenodd consumer " + value );
if((list.get(0)%2)==0){
if(oddb=true){
odd.acquire();
oddb=false;
}
if(evenb==false){
even.release();
evenb = true;
}
}
else if((list.get(0)%2)==1){
if(evenb=true){
even.acquire();
evenb=false;
}
if(oddb==false){
odd.release();
oddb = true;
}
}
System.out.println(list);
mutex.release();
empty.release();
}
}
}
package lab61;
import lab6.producer;
public class App {
public static void main(String[] args) throws InterruptedException{
Process p=new Process(10);
Thread producer1=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.Producer();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread producer2=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.Producer();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread producer3=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.Producer();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumereven1=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumereven();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumereven2=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumereven();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumerodd1=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumerodd();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumerodd2=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumerodd();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread evenodd1=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.evenodd();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread evenodd2=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.evenodd();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
producer1.start();
producer2.start();
producer3.start();
consumereven1.start();
consumereven2.start();
consumerodd1.start();
consumerodd2.start();
evenodd1.start();
evenodd2.start();
producer1.join();
producer2.join();
producer3.join();
consumereven1.join();
consumereven2.join();
consumerodd1.join();
consumerodd2.join();
evenodd1.join();
evenodd2.join();
}
}
The code can cause a deadlock because consumereven() and consumerodd() methods acquire the even or odd semaphore before the full and mutex semaphores, while the evenodd() method acquires the full and mutex semaphores before the even or odd semaphore. This results in a situation where, say, a thread running consumereven() has the even semaphore but is blocked while waiting on the full semaphore, while a thread running evenodd() has the full semaphore, but is blocked on the even semaphore, so the two threads are deadlocked.
To help prevent deadlocks, when you use multiple locks, it's best always to acquire them in the same order wherever they are used, and release them in the reverse order of acquisition.
Not a Great way of doing it but u could do something like.
import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class P1 {
Semaphore empty;
Semaphore full;
Semaphore even;
Semaphore odd;
Semaphore mutex;
Semaphore oddeven;
LinkedList<Integer> list;
Random random;
boolean oddb;
boolean evenb;
boolean oddevenb;
public P1(int capacity){
list=new LinkedList<Integer>();
empty=new Semaphore(capacity,true);
full=new Semaphore(0,true);
mutex=new Semaphore(1,true);
even=new Semaphore(0,true);
odd=new Semaphore(0,true);
oddeven=new Semaphore(0,true);
oddb=false;
evenb=false;
oddevenb = false;
random=new Random();
}
public void Producer(String s) throws InterruptedException{
while(true){
int a=random.nextInt(100);
empty.acquire();
mutex.acquire();
list.add(a);
System.out.println("Producing "+a+" By "+s);
System.out.println(list);
int temp=random.nextInt(3)+1;
if(temp==1 ){
if(oddevenb==false){
oddeven.release();
oddevenb=true;
evenb=true;
oddb=true;
}
}
else{
if((list.get(0))%2==0){
if(evenb==false){
even.release();
evenb=true;
oddevenb=true;
}
}else if((list.get(0))%2==1){
if( oddb==false) {
odd.release();
oddevenb=true;
oddb=true;
}
}
}
mutex.release();
full.release();
}
}
public void consumereven(String s) throws InterruptedException{
while(true){
// Thread.sleep(5000);
even.acquire();
full.acquire();
mutex.acquire();
int value=list.removeFirst();
System.out.println("I am the "+ s +" consumer "+value);
evenb=false;
oddevenb=false;
System.out.println(list);
mutex.release();
empty.release();
}
}
public void consumerodd(String s) throws InterruptedException{
while(true){
//Thread.sleep(5000);
odd.acquire();
full.acquire();
mutex.acquire();
int value= list.removeFirst();;
System.out.println("I am the "+s+" consumer "+value);
oddb=false;
oddevenb=false;
System.out.println(list);
mutex.release();
empty.release();
}
}
public void consumeroddeven(String s) throws InterruptedException{
while(true){
//Thread.sleep(5000);
oddeven.acquire();
full.acquire();
mutex.acquire();
int value= list.removeFirst();;
System.out.println("I am the "+s+" "+value);
System.out.println(list);
oddevenb=false;
evenb=false;
oddb=false;
mutex.release();
empty.release();
}
}
}
public class App3 {
public static void main(String[] args) throws InterruptedException{
final P1 p=new P1(10);
Thread producer=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.Producer("p1");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread producer2=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.Producer("p2");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread producer3=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.Producer("p3");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},"p3");
Thread consumereven=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumereven("even1");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumereven2=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumereven("even2");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumerodd=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumerodd("odd1");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumerodd2=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumerodd("odd2");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumer=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumeroddeven("NC1");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread consumer1=new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
p.consumeroddeven("NC2");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
producer.start();
producer2.start();
producer3.start();
consumereven.start();
consumereven2.start();
consumerodd.start();
consumerodd2.start();
consumer.start();
consumer1.start();
producer.join();
producer2.join();
producer3.join();
consumereven.join();
consumereven.join();
consumereven2.join();
consumerodd.join();
consumerodd.join();
consumerodd2.join();
consumer.join();
consumer1.join();
}
}
Related
I have to make an assignment with multi-threading. I have 2 classes for movement of a crane.
In this cases class there are 2 options, whether the claws ultrasonic sensor sees a box or not (seen down below).
In the other class i have to pick up a box from the initial starting position and put it to another position from 1-3(which is a distance based on keypress).
How do i write the class I am missing?
public class Cases extends Thread
UltrasonicSensor usc= new UltrasonicSensor(SensorPort.S1);
int box=0;
boolean isBoxThere=true;
public Cases cases;
public void error() throws InterruptedException
{
LCD.drawString("There are no boxes", 0, 0);
LCD.drawString(" At the location", 0, 1);
Button.waitForAnyPress();
LCD.clear();
Thread.sleep(1000);
}
//Claw movement
public void down() throws InterruptedException{
MotorPort motorY=MotorPort.B;
motorY.resetTachoCount();
motorY.controlMotor(85, 1);
stopY();
}
public void up() throws InterruptedException{
MotorPort motorY = MotorPort.B;
motorY.controlMotor(85, 2);
while(motorY.getTachoCount()>0); //After the crane grabs the box it lifts it back up
stopY();
}
public void clawclose() throws InterruptedException{
MotorPort motorC=MotorPort.C;
motorC.controlMotor(65, 2);
{
Thread.sleep(505); //Thread sleep is used for the cranes precise stopping
}
motorC.controlMotor(100, 3);
{
Thread.sleep(1000);
}
stopC();
}
public void clawopen() throws InterruptedException{
MotorPort motorC=MotorPort.C;
{
Thread.sleep(520);
}
motorC.controlMotor(100, 3);
{
Thread.sleep(1000);
}
stopC();
}
//Codes for stopping of Motors
public static void stopY () throws InterruptedException{
MotorPort motorY = MotorPort.B;
motorY.controlMotor(100, 3);
Thread.sleep(1000);
}
public static void stopC () throws InterruptedException{
MotorPort motorC = MotorPort.C;
motorC.controlMotor(100, 3);
Thread.sleep(1000);
}
public void run()
{
try
{
while(true)
{
switch(box)
{
case 1:
{
while(box==1)
{
isBoxThere=true;
try {
clawopen();
} catch (InterruptedException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
try {
down();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(usc.getDistance()<10)
{
try
{
Thread.sleep(100);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
try
{
clawclose();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
case 2:
{
while(box==0)
{
isBoxThere=false;
try
{
error();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
}
finally{}
}
}
If i know a specific thread id. How to do the following?
Thread.getThreadById(id).continueWork();
Is it possible?
public class Test implements Runnable {
public void run() {
while(true){
pause();
doSomework();
}
}
private void doSomework() {
System.out.println("do some work");
}
public synchronized void pause() {
if (Tester.waitCondition == true) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void continueWork() {
notify();
}
}
public class Tester {
public static boolean waitCondition = true;
public static void main(String[] args) {
Thread nThread = new Thread(new Test());
nThread.start();
waitCondition = false;
Thread nThread1 = new Thread(new Test());
nThread1.start();
Thread nThread2 = new Thread(new Test());
nThread2.start();
Thread nThread3 = new Thread(new Test());
nThread3.start();
Long id = nThread.getId();
Thread.getThreadById(id).continueWork();
}
}
You need block the thread with a lock , then call the lock's notify method to set blocked thread runnable .
If more than one thread to be continued , you will need Condition .
Like blow:
final Lock lock = new ReentrantLock();
final Condition condition1 = lock.newCondition();
final Condition condition2 = lock.newCondition();
Thread t = new Thread() {
#Override
public void run() {
try {
lock.lock();
condition1.await();
System.out.println("end cdt1");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
t.start();
Thread t1 = new Thread() {
#Override
public void run() {
try {
lock.lock();
condition2.await();
System.out.println("end cdt2");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
t1.start();
Thread.sleep(1000);
Thread tt = new Thread() {
#Override
public void run() {
try {
lock.lock();
condition1.signal();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
tt.start();
Thread.sleep(2000);
Thread tt1 = new Thread() {
#Override
public void run() {
try {
lock.lock();
condition2.signal();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
tt1.start();
Elaborating:
public class Tester {
// Apologies, I'm too lazy to create two separate files
static public class Test implements Runnable {
private void doSomework() {
System.out.print(
"do some work on Thread: "
+Thread.currentThread().getId()
);
try {
Thread.sleep(500); // just to simulate a load
}
catch(InterruptedException e) {
// ignore
}
}
public void run() {
do {
boolean shouldIWait=true;
synchronized(Tester.lockingObj) {
Boolean flag=Tester.waitConditions.get(Thread.currentThread().getId());
if(null!=flag) {
shouldIWait=flag.booleanValue();
} // if null, the tester started me before creating my flag. I'll wait
if(shouldIWait) {
// I need to wait for someone to wake me
try {
Tester.lockingObj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
// well, I'm interrupted, so I'll do no more work.
break;
}
}
}
if(false==shouldIWait) {
// waiting no more
this.doSomework();
}
} while(true);
}
}
public static Object lockingObj=new Object();
public static TreeMap<Long, Boolean> waitConditions=
new TreeMap<Long, Boolean>();
public static void main(String[] args) {
Thread nThread = new Thread(new Test());
Thread nThread1 = new Thread(new Test());
Thread nThread2 = new Thread(new Test());
Thread nThread3 = new Thread(new Test());
// when starting, all threads will be waiting
waitConditions.put(nThread.getId(), true);
waitConditions.put(nThread.getId(), true);
waitConditions.put(nThread.getId(), true);
waitConditions.put(nThread.getId(), true);
nThread2.start();
nThread1.start();
nThread.start();
nThread3.start();
Long id = nThread.getId();
synchronized (lockingObj) { // when notified, all thread should wakeup
waitConditions.put(id, false); // but only nThread will be allowed to doSomeWork
lockingObj.notifyAll(); // wake up all the threads.
// Those not allowed, will go into
// back waiting
}
try {
// just to have the main thread still running for a while
Thread.sleep(3000);
} catch (InterruptedException e) {
}
// maybe we want to switch of nThread and start another?
synchronized (lockingObj) {
waitConditions.put(id, true);
waitConditions.put(nThread1.getId(), false);
lockingObj.notifyAll();
}
try {
// just to have the main thread still running for a while
Thread.sleep(3000);
} catch (InterruptedException e) {
}
}
}
I Have class to record sound in my android project .
In this class i have 2 function : start() and stop()
and i have a main class I want run it from other activity such : record(second)
and record some time and stop aoutomaticly after those second !
Like this :
start();
//sleep(second)
stop();
How I can do this ?
this is my code :
package com.example.voicerec;
import java.io.IOException;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Environment;
import android.view.View;
public class VoiceR {
private MediaRecorder myRecorder;
private MediaPlayer myPlayer;
private String outputFile = null;
public void Record()
{
outputFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/momeni.3gpp";
myRecorder = new MediaRecorder();
myRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myRecorder.setAudioEncoder(MediaRecorder.OutputFormat.THREE_GPP);
myRecorder.setOutputFile(outputFile);
}
public void start(View view) {
try {
myRecorder.prepare();
myRecorder.start();
}
catch (IllegalStateException e) {
// start:it is called before prepare()
// prepare: it is called after start() or before setOutputFormat()
e.printStackTrace();
}
catch (IOException e) {
// prepare() fails
e.printStackTrace();
}
}
public void stop(View view) {
try {
myRecorder.stop();
myRecorder.release();
myRecorder = null;
}
catch (IllegalStateException e) {
// it is called before start()
e.printStackTrace();
}
catch (RuntimeException e) {
// no valid audio/video data has been received
e.printStackTrace();
}
}
public void play(View view) {
try {
myPlayer = new MediaPlayer();
myPlayer.setDataSource(outputFile);
myPlayer.prepare();
myPlayer.start();
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void stopPlay(View view) {
try {
if (myPlayer != null) {
myPlayer.stop();
myPlayer.release();
myPlayer = null;
}
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Just make a thread that runs start then sleeps for record time then runs stop :
final int time = second * 1000;
Thread sound = new Thread(new Runnable() {
#Override
public void run() {
start(view);
try{
Thread.sleep(time);
}catch(Exception e){}
stop();
}
});
sound.start();
or you can use CountDownLatch :
CountDownLatch latch = new CountDownLatch(1);
start(view);
Thread stopping = new Thread(new Runnable() {
#Override
public void run() {
try {
latch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
stop(view);
}
});
stopping.start();
and after the recording process finished:
latch.countDown();
I'm a little stumped. Below is pretty much a copy and paste from A simple scenario using wait() and notify() in java.
To my understanding, this Java program below should be printing yumyum.. to the screen but it isn't. I am in Eclipse for Mac OS X. Any ideas what I'm doing wrong ?
public class Main {
public static void main(String[] args) {
MyHouse house = new MyHouse();
house.eatPizza();
house.pizzaGuy();
}
}
class MyHouse extends Thread {
private boolean pizzaArrived = false;
public void eatPizza() {
synchronized (this) {
while (!pizzaArrived) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
System.out.println("yumyum..");
}
public void pizzaGuy() {
synchronized (this) {
this.pizzaArrived = true;
notifyAll();
}
}
}
You have one thread. The single thread will wait indefinitely (it needs to be notified by another thread). Try creating another thread in which one will eatPizza() and one will pizzaGuy
Try this...
public class Main {
public static void main(String[] args) {
MyHouse house = new MyHouse();
house.start();
// house.eatPizza();
// Halt main thread momentarily to delay Mr Pizza Guy
try { Thread.sleep(3000); } catch(Exception e) {}
house.pizzaGuy();
}
}
class MyHouse extends Thread {
private boolean pizzaArrived = false;
private Object lock = new Object();
#Override
public void run() {
eatPizza();
}
public void eatPizza() {
synchronized (lock) {
while (!pizzaArrived) {
try {
System.out.println("Waiting for Pizza guy");
lock.wait();
} catch (InterruptedException e) {
}
}
System.out.println("Pizza arrived!!!");
}
System.out.println("yumyum..");
}
public void pizzaGuy() {
synchronized (lock) {
this.pizzaArrived = true;
lock.notifyAll();
}
}
}
Try below code working fine.
public class WaitNotify {
private static int i = 1;
private static boolean flag = false;
static Object obj = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable(){
#Override
public void run() {
while(i<10){
synchronized (obj) {
try {
if(i%2 == 0){
obj.wait();
}
System.out.println("t1 -> " + i++);
obj.notify();
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});
Thread t2 = new Thread(new Runnable(){
#Override
public void run() {
while(i<10){
synchronized (obj) {
try {
if(i%2 != 0){
obj.wait();
}
System.out.println("t2 -> " + i++);
obj.notify();
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I'm trying to write a program, which starts an process for the windows console (cmd) and redirects the Input,Output and Errorstreams to System.in/out/err. Also, if the process is closed (via the command exit) my program should shutdown.
I've written a solution, that works kind of. The only problem is my used thread don't notice the process is shutted down. Also I don't know if it is nessecery to write a new Thread for all this streams, so if you know an easier solution to redirect the streams I'd like to hear about it.
Here my SSCCE:
public class Main {
public static boolean run = true;
public static void main(String[] args) throws IOException {
ProcessBuilder p = new ProcessBuilder("cmd");
final Process pr = p.start();
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
pr.waitFor();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test");
run = false;
}
});
// read(is);
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(System.in, pr.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(pr.getInputStream(), System.out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("finish");
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(pr.getErrorStream(), System.err);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
public static void write(InputStream is, OutputStream os)
throws IOException {
byte[] buf = new byte[1024];
int len = is.read(buf);
if (len != -1) {
byte[] data = new byte[len];
for (int i = 0; i < len; i++) {
data[i] = buf[i];
}
os.write(data);
os.flush();
}
}
}
What happens, is that I create a new Thread for every redirection of the streams, and the redirection itself happens via the write(inputStream,outputStream) method.
But the thread I use to check if the process is closed (pr.waitFor()) doesn't work as i thought it would. So I don't get noticed if the cmd is closed.
EDIT2
Ok I just forgot to start the Thread. But now I was able to get close to the problem.
The redirection of System.in to the process.getOutputStream() doesn't notice that the process is going to be closed. That's because is.read(buf) is a blocking method. So if I try to write a new command to the Process, then it notices that the streams should be closed and finishes the program.
If there is any solution for redirecting the Streams without threads, I'd like to implement it that way. I think this would be easier to use.
the main problem is you didn't do .start on the thread but i also want to suggest an improvement
wait for the process in the main thread:
public class Main {
public static boolean run = true;
public static void main(String[] args) throws IOException {
ProcessBuilder p = new ProcessBuilder("cmd");
final Process pr = p.start();
// read(is);
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(System.in, pr.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(pr.getInputStream(), System.out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("finish");
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (run)
try {
write(pr.getErrorStream(), System.err);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
try {
pr.waitFor();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test");
run = false;
}
public static void write(InputStream is, OutputStream os)
throws IOException {
byte[] buf = new byte[1024];
int len = is.read(buf);
if (len != -1) {
byte[] data = new byte[len];
for (int i = 0; i < len; i++) {
data[i] = buf[i];
}
os.write(data);
os.flush();
}
}
}
I'm guessing that is because your main thread could exit before all those threads complete. Try adding pr.waitFor() right at the end of your main function.