从java中的另一个线程访问一个线程的变量

Posted

技术标签:

【中文标题】从java中的另一个线程访问一个线程的变量【英文标题】:Accessing a variable of a thread from another thread in java 【发布时间】:2013-07-19 08:08:28 【问题描述】:

我正在尝试访问和修改java中另一个线程中的一个线程的变量,我真的不知道该怎么做。

前:

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中的线程创建getter和setter?

编辑:答案很好,但我的问题不清楚,我会尝试问一个更好的问题

【问题讨论】:

线程没有变量。类有成员,方法有参数和局部变量。如果您按照这些思路重新分析您的问题,答案应该是显而易见的。 【参考方案1】:

创建一个runnable,并使用您在该runnable 中定义的setter 和getter。

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 关键字就没有必要了。

为了证明我的观点,上面的代码和下面的代码都是线程安全的,但不同的是,在下面的例子中没有两个线程可以同时输入setStringgetString

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();

对原语使用原子值很好,但如果您想共享更复杂的对象,则必须阅读threading and synchronization.

例如:

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 关键字会锁定使用自己作为同步对象的类。

最后一点,同步关键字不仅仅用于方法定义。您可以使用它来同步方法中的实例,就像我在 StatRunnable 中的 run 方法中所做的那样。

【讨论】:

你能提供一个线程安全的例子吗?这看起来像原始代码,但具有 setter/getter 以及对字段的直接访问。 这是线程安全的,因为没有任何东西触及字符串 :) 但是是的,我会写一个更复杂的例子。 AFAIK 你已经用String myString = runnable.getString(); 替换了String myString = runnable.myString;,它做同样的事情。 我知道,迟到几年总比没有好,但您的解决方案效果很好。谢谢! @kpont 很高兴听到这个消息!希望它在线程方面对您有所帮助,这是一个复杂的主题。【参考方案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 来引用对象。

【讨论】:

以上是关于从java中的另一个线程访问一个线程的变量的主要内容,如果未能解决你的问题,请参考以下文章

将数据从UI线程传递到c#中的另一个线程

访问 UI 组件并由 Xamarin 中的另一个线程覆盖它

从 Java Swing 中的另一个类访问 JPanel 变量

java多线程2.线程安全之可见性

Java 基础系列之volatile变量

Java中的ThreadLocal详解