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

在java中限制从三个线程访问三个对象上的方法,java,multithreading,Java,Multithreading,我在一次采访中被问到一个问题。 问题如下: 有一个类Employee,其中有一个名为getDetail()的方法。 我们将这个类的三个对象设置为e1,e2和e3,并将其传递给三个不同的线程,即t1,t2和t3。 现在开始线程。 我们如何限制线程访问getDetail方法,以便一次只能有一个线程访问该方法。 我的意思是,如果t1在getDetail方法中,那么没有其他线程可以访问Employee类的getDetail方法 提前感谢您的帮助。您可以这样标记方法 class Employee {

我在一次采访中被问到一个问题。 问题如下: 有一个类
Employee
,其中有一个名为
getDetail()
的方法。 我们将这个类的三个对象设置为
e1
e2
e3
,并将其传递给三个不同的线程,即
t1
t2
t3
。 现在开始线程。 我们如何限制线程访问
getDetail
方法,以便一次只能有一个线程访问该方法。 我的意思是,如果
t1
getDetail
方法中,那么没有其他线程可以访问
Employee
类的
getDetail
方法

提前感谢您的帮助。

您可以这样标记方法

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

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


如果您需要其他方法,如
setDetail(EmployeeDetail)
,则可以将它们标记为
synchronized
,这将正确设置
EmployeeDetail
参考

根据我的理解,我认为让线程限制
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;
    }
}
import java.util.ArrayList;
公共类线程{
公共静态void main(字符串[]args)引发InterruptedException{
//TODO自动生成的方法存根
员工e1=新员工(“e1”);
ArrayList emps=新的ArrayList();
环境管理计划增补(e1);
ThreadEmployee t=新ThreadEmployee(emps);
螺纹t1=新螺纹(t);
螺纹t2=新螺纹(t);
t1.集合名(“t1”);
t2.设定名称(“t2”);
t1.start();t2.start();
t1.join();t2.join();
对于(员工e:emps)
{
System.out.println(e.getDetail());
}
}
}
类ThreadEmployee实现Runnable{
私人ArrayList EMP;
ThreadEmployee(ArrayList emps){
this.emps=emps;
}
公开募捐{
//TODO自动生成的方法存根
对于(员工e:emps)
{
e、 changeDetail(例如getDetail()+“-”+Thread.currentThread().getName());
}
}
}
班级员工{
私有字符串名称;
雇员(){
}
雇员(字符串名称){
this.name=名称;
}
公共字符串getDetail(){
返回名称;
}
已同步的公共void changeDetail(字符串名称){
this.name=名称;
}
}

甚至我也不知道线程是如何执行的,它完全掌握在JVM的手中,但到最后,我可以确定一次只有一个对象访问changeDetails方法。不会有任何数据失实。

谢谢您的回答。据我所知,同步工作在同一个对象上,但这里的对象是不同的。我的回答是一样的,但面试官对答案不满意。我的答案是,只有当不同的线程访问同一个对象时,才会考虑线程安全问题。在这里,每个线程都有一个单独的对象。它可以是为员工设定任何价值或更新任何价值的任何方法。@Rajeev我不知道面试官提出这样的问题时是怎么想的。