I have the following code:
public class Shell {
String status;
Runtime rtime;
Process process;
public void runCmd(final String cmd,String status) throws Exception{
this.status = status;
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
process = rtime.exec(cmd);
process.waitFor();
this.status = "check out done";
} catch (IOException e) {
} catch (InterruptedException e) {
}
}
});
t.start();
}
}
but java doesn't let me change the status variable inside the new thread t.May be I need some sort of inter thread communication.I am new to threads,please tell me how to do this.
In your case this in expression this.status refers Runnable object which does not have status field defined. Try Shell.this.status instead of this.status.
The problem is that you cannot access a variable from a parent class in an anonymous class unless it is final and even then it is complex. As you want to modify it I would suggest something like:
public class Holder <T> {
private T held = null;
public Holder () {
}
public Holder (T it) {
held = it;
}
public void hold(T it) {
held = it;
}
public T held() {
return held;
}
#Override
public String toString () {
return held == null ? "null": held.toString();
}
}
Then your code can look like this:
public class Shell {
final Holder<String> status = new Holder<>();
Runtime rtime;
Process process;
public void runCmd(final String cmd, String status) throws Exception {
// Set the status.
Shell.this.status.hold(status);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
process = rtime.exec(cmd);
process.waitFor();
Shell.this.status.hold("check out done");
} catch ( IOException | InterruptedException e) {
}
}
});
t.start();
}
}
Added
This demopnstration of the use of a Holder is the solution to a different problem - i.e. the need to modify a final object from inside an anonymous class.
This answer is not the solution to OP's problem and I would delete it if I could. Unfortunately it has been marked as the answer so I cannot.
If OP could mark one of the other posts as the correct answer I would be happy to delete this.
public class Shell {
volatile String status;
public void runCmd(final String cmd) throws Exception{
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Process process = Runtime.getRuntime().exec(cmd);
process.waitFor();
Shell.this.status = "check out done";
} catch (IOException e) {
} catch (InterruptedException e) {
}
}
});
t.start();
t.join();
System.out.println(status);
}
}
Use Shell.this.status and update the value to what to want.
Thread Safety
Always use volatile when reference is updated from another thread.
Related
I am trying to create a synchronized version of data and using junit to test my method. The code below is what I came so far. It works quite well if I put on the main method (the counter is increased one by one by each thread) but the test process will stop immediately. Is this the problem by using Thread.sleep() on a test case?
public void testGeneral() {
class SynchronizedData {
public AtomicBoolean lock = new AtomicBoolean(false);
public int counter = 0;
public void update() {
if(lock.compareAndSet(false, true)) {
counter++;
System.out.println(counter);
lock.set(false);
}
}
}
SynchronizedData data = new SynchronizedData();
class Handler implements Runnable {
String name;
public Handler(String name) {
this.name = name;
}
#Override
public void run() {
for(;;) {
try {
Thread.sleep(new Random().nextInt(100));
} catch (InterruptedException e) {
System.out.println(e);
}
System.out.println(this.name);
data.update();
}
}
}
new Thread(new Handler("One")).start();
new Thread(new Handler("Two")).start();
}
I'm looking to use a thread to process something in the background. Since this code isn't used anywhere else & is not complex I'd like to use an inline function. However the function needs a copy of an attribute at the time the thread was created i.e.: I'd like it if the output from the following example 'true' instead of 'false'
public class InlineThreadTest {
boolean value;
public static void main(String[] args) {
new InlineThreadTest();
}
InlineThreadTest() {
value = true;
java.util.concurrent.Executors.newSingleThreadExecutor().execute(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
System.out.println(value);
}
});
value = false;
}
}
... I can do what I'm looking to do by creating a separate class that implements Runnable, but having this inline seems like something that might be good.
I had a look # https://stackoverflow.com/a/362443/64696 , but cannot figure out how to mold this to my use case.
Runnable implementation is a thread and thread won't return any value. The ExecutorService.execute method just runs the thread and you have no way to get the state of the thread whether it was executed or not.
If you want to check for the task (not thread) executed by ExecutorService you should use Callable and work with sumbit(). Your modified example:
public class InlineThreadTest {
boolean value;
public static void main(String[] args) {
new InlineThreadTest();
}
InlineThreadTest() {
value = true;
java.util.concurrent.Future<Boolean> f =
java.util.concurrent.Executors.newSingleThreadExecutor().submit(new Callable<Boolean>() {
public Boolean call() {
System.out.println(value);
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
value = false;
return value;
}
});
try {
System.out.println(f.get()+" or value="+value);
} catch (Exception ex) { }
}
}
You'll get 2 lines
true
false or value=false
I'm using a few services inheriting from the AbstractScheduledService, which get managed by a ServiceManager. Everything works fine, but now, there's a service whose runOneIteration takes a rather long time, and as the result, my process takes too long to terminate (more than five seconds).
There are other services inheriting from AbstractExecutionThreadService, which had a similar problem, which I could solve via
#Override
protected final void triggerShutdown() {
if (thread != null) thread.interrupt();
}
and storing private volatile thread in the run method. However, there's no triggerShutdown for AbstractScheduledService as stated in this issue.
I already considered alternatives like making runOneIteration do less work, but it's both ugly and inefficient.
I can't override stopAsync as it's final and I can't see anything else. Is there a hook for doing something like this?
Can you work with this? Was there any reason you couldn't add a triggerShutdown yourself?
class GuavaServer {
public static void main(String[] args) throws InterruptedException {
GuavaServer gs = new GuavaServer();
Set<ForceStoppableScheduledService> services = new HashSet<>();
ForceStoppableScheduledService ts = gs.new ForceStoppableScheduledService();
services.add(ts);
ServiceManager manager = new ServiceManager(services);
manager.addListener(new Listener() {
public void stopped() {
System.out.println("Stopped");
}
public void healthy() {
System.out.println("Health");
}
public void failure(Service service) {
System.out.println("Failure");
System.exit(1);
}
}, MoreExecutors.directExecutor());
manager.startAsync(); // start all the services asynchronously
Thread.sleep(3000);
manager.stopAsync();
//maybe make a manager.StopNOW()?
for (ForceStoppableScheduledService service : services) {
service.triggerShutdown();
}
}
public class ForceStoppableScheduledService extends AbstractScheduledService {
Thread thread;
#Override
protected void runOneIteration() throws Exception {
thread = Thread.currentThread();
try {
System.out.println("Working");
Thread.sleep(10000);
} catch (InterruptedException e) {// can your long process throw InterruptedException?
System.out.println("Thread was interrupted, Failed to complete operation");
} finally {
thread = null;
}
System.out.println("Done");
}
#Override
protected Scheduler scheduler() {
return Scheduler.newFixedRateSchedule(0, 1, TimeUnit.SECONDS);
}
protected void triggerShutdown() {
if (thread != null) thread.interrupt();
}
}
}
I'm doing a thread who tells me when an event happens. I think that thread is not necessary if event can be controlled by timer for example. But I need an event every minute. Trouble are two:
1. When event is inside a thread occurs too fast. It seems like loop over thread. But threads are necessary to listen or catch an event.
2. I can't tell method which custom object must dispatch event, and then capture this event from a new class
I hope that you can help, here is code:
import java.util.Observer;
import java.util.Observable;
public class Main {
public static void main(String[] args) {
Threading test = new Threading();
test.start();
}
}
class ResponseHandler implements Observer {
#Override
public void update(Observable obj, Object arg) {
if (arg instanceof String) {
String resp = (String) arg;
System.out.println("\n Received response: " + resp);
}
}
}
class EventSource extends Observable implements Runnable {
#Override
public void run() {
try {
while (true) {
Object msg = new Object(); //I guess that this must have an object here, that throws a timeout
setChanged();
notifyObservers(msg);
}
} catch (Exception e) { e.printStackTrace();}
}
}
class Obj {
EventSource _eventSource;
ResponseHandler _responseHandler;
public Obj() {
try {
_eventSource = new EventSource();
_responseHandler = new ResponseHandler();
_eventSource.addObserver(_responseHandler);
} catch (Exception ex) {
System.out.print(ex);
}
}
}
class Threading extends Obj implements Runnable {
Thread _thread;
public void run() {
while (true) {
try {
_eventSource.run(); //Event which never stops
Thread.sleep(1000); //hey thread what are you doing?
} catch (InterruptedException ex) {
}
System.out.println("Thread");
}
}
//Singlethon
public void start() {
if (_thread == null) {
_thread = new Thread(this);
_thread.start();
}
}
}
I have a pool of worker threads (an ExecutorService).
This pool is used to run shell commands.
I use a shell (/bin/sh) rather than creating a process for the executable directly, because I use shell redirects (>) to write the output directly to disk, without having to pass through the JVM, as well as some other niceties.
Spawning a shell process takes 2-3 milliseconds.
I want each thread to keep a shell process to avoid the overhead of starting it.
How do I allow each thread to own a process?
I am thinking of using a ThreadFactory with thread locals.
class ThreadFactory {
Thread newThread(Runnable r) {
return new Thread(new Runnable() {
Process process = Runtime.getRuntime().exec("/bin/sh")
try {
// store process as thread local here
r.run(); // then r can access thread local
} catch(Exception e) {
try {
process.close();
} catch(Exception e) {
}
throw e;
}
});
}
}
(Alternatively, I could subclass Thread and cast Thread.currentThread() to that class in my Runnable.)
Is this a good approach to solving this problem?
I would keep the Process reference in a ProcessRunnable that continuously executes commands. I think is more clear than using a ThreadLocal and a ThreadFactory. Something like this:
public class ShellCommandExecutor {
private int concurrency = 10;
private int capacity = 100;
private ExecutorService service = Executors.newFixedThreadPool(concurrency);
private BlockingQueue<String> commandsQueue = new LinkedBlockingQueue<>(capacity);
public void start() {
for (int i = 0; i < concurrency; i++)
service.submit(new Runnable() {
#Override
public void run() {
//todo deal with ioexception
Process process = Runtime.getRuntime().exec("/bin/sh");
while (!Thread.currentThread().isInterrupted()) {
try {
String command = commandsQueue.take();
//todo execute commands using the same process per thread
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
});
}
public void executeCommand(String command) throws InterruptedException {
commandsQueue.put(command);
}
public void shutdown() {
service.shutdownNow();
}
}
EDIT: a solution with thread local that should work easily with cached thread pools:
public class ShellCommandExecutor2 {
//todo limit queue
private ExecutorService service = Executors.newCachedThreadPool();
public void executeCommand(final String command) throws InterruptedException {
service.submit(new Runnable() {
#Override
public void run() {
Process process = ThreadLocalProcessFactory.get();
//todo execute command
}
});
}
public void shutdown() {
service.shutdownNow();
}
private static class ThreadLocalProcessFactory {
private static final ThreadLocal<Process> processThreadLocal =
new ThreadLocal<Process>() {
#Override protected Process initialValue() {
try {
return Runtime.getRuntime().exec("/bin/sh");
}
catch (IOException e) {
e.printStackTrace();
return null;
}
}
};
static Process get() {
return processThreadLocal.get();
}
}
}