Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使应用程序构建块线程安全?_Java_Multithreading_Thread Safety - Fatal编程技术网

Java 如何使应用程序构建块线程安全?

Java 如何使应用程序构建块线程安全?,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我有很多遗留代码,这些代码在很大程度上由具有以下结构的类组成: public interface MyFunctionalBlock { // Setters for the inputs void setInput1(final int aInput1); void setInput2(final Object aInput2); // Inside the method run inputs are converted into results vo

我有很多遗留代码,这些代码在很大程度上由具有以下结构的类组成:

public interface MyFunctionalBlock
{
    // Setters for the inputs
    void setInput1(final int aInput1);
    void setInput2(final Object aInput2);

    // Inside the method run inputs are converted into results
    void run();

    // If this building block needs functionality from some other building blocks,
    // it gets a reference to them from the Google Guice injector.
    void setInjector(final Injector aInjector);

    // Getters for the results
    long getResult1();
    Object getResult2();
    Map<String,String> getResult3();
}

public class MyFunctionalBlockFactory implements Factory<MyFunctionalBlock>
{
    public MyFunctionalBlock create()
    {
        return new DefaultMyFunctionalBlock();
    }
}

class DefaultMyFunctionalBlock implements MyFunctionalBlock
{
    private int input1;
    private Object input2;
    private long result1;
    private long result2;
    private Map<String,String> result3;
    private Injector injector;

    @Override
    public void run()
    {
        // Here the calculations are performed.

        // If this functional block needs another one, it gets a reference to it using the injector.
        // AnotherFunctionalBlock is the public interface. Implementations of the interface are 
        // intentionally hidden using injector and package-private declaration.
        final AnotherFunctionalBlock fb = injector.getInstance(AnotherFunctionalBlock.class);

        // First, we set the inputs

        fb.setInput1(...);
        fb.setInput2(...);

        [...]

        fb.setInputN(...);

        // Now we run the calculation

        fb.run();

        // Now we can use the results
        fb.getResult1();
        fb.getResult2();

        [...]

        fb.getResultN();
    }

    // Implementation of getters and setters omitted
}
更新1(09.06.2013 21:57 MSK):一个潜在的重要注意事项-并发性源于这样一个事实:有N个web服务接收请求,然后使用旧代码根据该请求进行计算,并将结果返回给web服务客户端

一个潜在的解决方案是在web服务和旧代码之间添加某种队列

更新2:

我考虑了如何以尽可能少的努力使代码线程安全,并找到了以下解决方案(目前,我不关心性能)

有几个web服务类,它们都有一个后端属性并同时访问它

public class WebService1
{

  private Backend backend;

  public Response processRequest(SomeRequest1 request)
  {
    return wrapResultIntoResponse(backend.doSomeThreadUnsafeStuff1(request.getParameter1(), request.getParameter2()));
  }
}

public class WebService2
{ 
  private Backend backend;

  public Response processRequest(SomeRequest2 request)
  { 
    return wrapResultIntoResponse(backend.doSomeThreadUnsafeStuff2(request.getParameter1(), request.getParameter2(), request.getParameter3()));
  }
}
所有对非线程安全代码的调用都通过
后端
类进行(所有web服务都引用一个相同的
后端
实例)

如果我确保后端处理一个接一个的请求(并且从不同时处理两个请求),我就可以在不重新编写整个应用程序的情况下获得所需的结果

final AnotherFunctionalBlock fb = injector.getInstance(AnotherFunctionalBlock.class);

synchronized(fb)
{
    fb.setInput1(...);
    fb.setInput2(...);

    [...]

    fb.setInputN(...);

    fb.run();
    fb.getResult1();
    fb.getResult2();

    [...]

    fb.getResultN();        
}
下面是我对后端类的实现:

public class Backend
{ 
    private synchronized boolean busy = false;

    public Object doSomeThreadUnsafeStuff1(Long aParameter1, String aParameter2)
    {
        waitUntilIdle();

        synchronized (this)
        {

            busy=true;

            // Here comes the non-thread safe stuff 1

            busy=false;

            notifyAll();
        }
    }

    public Object doSomeThreadUnsafeStuff2(Long aParameter1, String aParameter2, Map<String,String> aParameter3)
    {
        waitUntilIdle();

        synchronized (this)
        {

        busy=true;

        // Here comes the non-thread safe stuff 2

        busy=false;
        notifyAll();
        }
    }
    private void waitUntilIdle()
    {
      while (busy)
      {
        wait();
      }
    } 
}
公共类后端
{ 
私有同步布尔忙=假;
公共对象doSomeThreadUnsafeStuff1(长APParameter1,字符串APParameter2)
{
waitUntilIdle();
已同步(此)
{
忙=真;
//下面是非线程安全的东西1
忙=假;
notifyAll();
}
}
公共对象doSomeThreadUnsafeStuff2(长APParameter1,字符串APParameter2,映射APParameter3)
{
waitUntilIdle();
已同步(此)
{
忙=真;
//下面是非线程安全的东西2
忙=假;
notifyAll();
}
}
私有void waitUntilIdle()
{
当(忙)
{
等待();
}
} 
}

这个解决方案行得通吗?

除了“使其多线程化”之外,还不清楚您想要实现什么。Java中的并发性是一个非常复杂的主题,对于如何将整个应用程序从单线程转换为多线程,您不会找到一个单一的、逐步的答案。如果你这样做,我会完全不相信这个答案。我建议你拿起,这类事情的事实参考。这就是解决这个问题所需要了解的内容。

除了“使其多线程化”之外,还不清楚您想要实现什么。Java中的并发性是一个非常复杂的主题,对于如何将整个应用程序从单线程转换为多线程,您不会找到一个单一的、逐步的答案。如果你这样做,我会完全不相信这个答案。我建议你拿起,这类事情的事实参考。这就是如何了解解决此问题所需的知识。

您在更新2中提出的解决方案将使整个应用程序线程安全。我将其总结为在web用户和实际业务代码之间放置一个facade/singleton层。遗留代码本身不是线程安全的,因此您必须重写它,但是由于您完全控制对它的访问并以单线程方式执行它,所以总体上是可以的。如果对底层业务代码有任何不受控制的访问,它显然会失败


你说“目前,我不在乎表现”。我希望你是对的,因为就锁争用而言,这是一个可怕的想法。但是,如果您所要做的只是将这个不安全的代码作为web服务公开,而不提供简单的访问,那么是的,将同步的单例外观放在顶部将起作用。

您在更新2中提出的解决方案将使整个应用程序线程安全。我将其总结为在web用户和实际业务代码之间放置一个facade/singleton层。遗留代码本身不是线程安全的,因此您必须重写它,但是由于您完全控制对它的访问并以单线程方式执行它,所以总体上是可以的。如果对底层业务代码有任何不受控制的访问,它显然会失败

你说“目前,我不在乎表现”。我希望你是对的,因为就锁争用而言,这是一个可怕的想法。但是,如果您所要做的只是将这些不安全的代码作为web服务公开,而不提供简单的访问,那么是的,将同步的单例外观放在顶部将起作用。

您在“更新2”中描述的内容与。如果您100%确信自己对性能一点也不关心——我的意思是潜在的非常糟糕的性能——并且永远不会,那么您所建议的是一个公平的解决方案,尽管您建议的实现在
等待()
的锁定(或缺少锁定)方面存在问题。看一看Actor或其他Actor框架可能会更好地为您服务

将参与者视为在单个线程中运行,并具有可以向其交付工作单元的FIFO队列。对于每一个工作单元,参与者都会以某种方式处理它,然后返回一个回复,您可以保证工作单元是串行处理的,而不是并行处理的

您称之为“后端”的是在一个或多个参与者中运行的代码,每个参与者都独立于其他参与者。这样的框架允许您采用类似于您所描述的方法,但可以扩展以提高性能,而无需花费太多精力,也无需您管理并发性。

您在“更新2”中描述的内容类似于。如果你100%确信你一点也不在乎性能——我的意思是潜在的非常糟糕的性能