限制从java中的三个线程访问三个对象的方法

时间:2015-10-13 06:15:26

标签: java multithreading

我在接受采访时被问到一个问题。 问题如下所述: 有一个类1.8.2,其中有一个名为Employee的方法。 我们将此课程的三个对象说成getDetail()e1e2并将其传递给三个不同的帖子e3t1t2 。 现在开始线程。 我们如何限制线程访问t3方法,以便一次只有一个线程可以访问该方法。 我的意思是说如果getDetail位于t1方法内,则其他任何线程都无法访问getDetail类的getDetail方法。

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

您可以将方法标记为synchronized,如此

class Employee {
    synchronized Detail getDetail() { ... }
}

然而,在您描述的情况下,不需要同步,因为每个线程都有自己的Employee实例。但是如果实例将在线程之间共享,或者Employee类具有static变量或类共享其中的一些数据,则需要它。 即使每个线程都有自己的实例,这也可能导致问题。

在最后一种情况下,如果方法返回一些复杂对象,也可能会出现问题,让我们将其称为EmployeeDetail。当您调用getDetail()时,您将收到对EmployeeDetail对象的引用,该对象可能不是线程安全的。因此,您需要使整个EmployeeDetail类线程安全。

如果您需要其他方法,例如setDetail(EmployeeDetail),则可以标记synchronized,这将正确设置EmployeeDetail引用。

答案 1 :(得分:0)

根据我的理解,我认为使线程限制getDetails方法是没有意义的,假设它是对象级方法。因为每个线程都有一个不同的对象。交叉没有变化。

提出问题的一个更好的方法是,将同一个对象传递给不同的线程,并询问它如何影响对象的属性,更多的是访问getDetails()的内容,而这只是返回值。更好地限制对更改对象属性的方法的访问。

import java.util.ArrayList;

public class Threading {

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        Employee e1 = new Employee("e1");

        ArrayList<Employee> emps = new ArrayList<Employee>();
        emps.add(e1);

        ThreadEmployee t = new ThreadEmployee(emps);

        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);

        t1.setName("t1");
        t2.setName("t2");

        t1.start(); t2.start();
        t1.join(); t2.join();

        for(Employee e: emps)
        {
            System.out.println(e.getDetail());
        }
    }
}

class ThreadEmployee implements Runnable {
    private ArrayList<Employee> emps;

    ThreadEmployee(ArrayList<Employee> emps) {
        this.emps = emps;
    }

    public void run() {
        // TODO Auto-generated method stub
        for(Employee e: emps)
        {
            e.changeDetail(e.getDetail() + "-" + Thread.currentThread().getName());
        }
    }
}

class Employee {
    private String name;

    Employee() {

    }

    Employee(String name) {
        this.name = name;
    }

    public String getDetail() {
        return name;
    }

    synchronized public void changeDetail(String name) {
        this.name = name;
    }
}

即使我不知道线程实际上如何执行它完全掌握在JVM手中,但最后我可以确定只有一个对象一次访问changeDetails方法。不会有任何数据的虚假陈述。