Доступ к переменной потока из другого потока в java
Я пытаюсь получить доступ и изменить переменную потока в другом потоке в java, и я действительно не знаю, как это сделать.
ex:
Runnable r1 = new Runnable() {
int value = 10;
public void run() {
// random stuff
}
}
Runnable r2 = new Runnable() {
public void run() {
// of course the bellow line will not work
r1.value--; // I want here to be able to decrement the variable "value" of r1
}
}
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
спасибо, если у вас есть любые идеи!
есть ли способ создать геттер и сеттер для потока в java?
EDIT: ответы были хорошими, но я не был ясен в своем вопросе, я попробую задать лучший вопрос
2 ответов
вы можете сделать это вроде работы, но я предлагаю вам использовать AtomicInteger который разделяется между потоками.
final AtomicInteger value = new AtomicInteger(10);
Runnable r1 = new Runnable() {
public void run() {
// random stuff using value
}
}
Runnable r2 = new Runnable() {
public void run() {
value.decrementAndGet();
}
}
вы можете использовать AtomicReference для ссылок на объекты.
создайте runnable и используйте сеттеры и геттеры, которые вы определяете в указанном runnable.
public class MyRunnable implements Runnable{
private volatile String myString;
public String setString(String value){this.myString = value;}
public String getString(){
return myString;
}
public void run(){}
}
Примечание volatile
ключевое слово используется здесь. Ключевое слово volatile гарантирует, что если эта строка изменится в одном потоке, все потоки увидят это изменение. Если вместо этого я гарантирую, что единственный доступ к объекту String осуществляется через синхронизированный контекст, ключевое слово volatile не будет необходимо.
чтобы продемонстрировать мою точку зрения, приведенный выше код и код ниже находятся потокобезопасным, но разные, нет 2 потоков может войти setString
и getString
одновременно в приведенном ниже примере.
public class MyRunnable implements Runnable{
private String myString;
public synchronized String setString(String value){this.myString = value;}
public synchronized String getString(){
return myString;
}
public void run(){}
}
поток действительно просто выполняет runnable. Вы можете использовать это так:
MyRunnable runnable = new MyRunnable();
Thread myThread = new Thread(runnable);
myThread.start();
String myString = runnable.getString();
использование атомарных значений для примитивов прекрасно, но если вы когда-нибудь захотите поделиться более сложным объектом, вам придется прочитать о многопоточность и синхронизация.
например:
public class Stats{
int iterations;
long runtime;
public Stats(){
iterations = 0;
runtime=0;
}
public synchronized void setIterations(int value){this.iterations = value;}
public synchronized void setRuntime(long milliseconds){
this.runtime = milliseconds;
}
public synchronized int getIterations(){
return iterations;
}
public synchronized long getRuntime(){return runtime;}
}
public class StatRunnable implements Runnable{
Stats stats;
boolean active;
public StatRunnable(){
this.active=true;
}
public Stats getStats(){
return stats;
}
long calculateRuntime(){return 0L;}
public void run(){
while(active){
//i'm synchronizing with stats to ensure no other thread alters values
//simultaneously.
synchronized(stats){
stats.setIterations(stats.getIterations()+1);
stats.setRuntime(calculateRuntime());
}
}
}
}
этот код показывает пример синхронизации с непримитивными объектами через synchronized
ключевое слово. Использование ключевого слова synchronized в определении метода блокирует класс, используя его в качестве объекта синхронизации.
последнее замечание, ключевое слово synchronized не просто используется в определениях методов. Вы можете использовать его для синхронизации экземпляров внутри методов, как я сделал в run
метод StatRunnable
.