Доступ к переменной потока из другого потока в 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.