误解ExecutorService - 我想

时间:2015-01-29 18:09:17

标签: java multithreading executorservice

我想开始一组10个线程。在我使用的主程序构造函数中:

executor = Executors.newFixedThreadPool(NTHREADS);

Callable<String> poller;
for (int i = 0; i < NTHREADS; ++i) {
    Future<String> future = executor.submit(new Poller(0x3A, m_socket, ds_in, ds_out, socketLock));
    set.add(future);
}

对于Poller类中的call()方法,我有:

public String call()
{
    // This has to be set here, otherwise all threads will have a name of "main".
    myID = Thread.currentThread().getName();

    boolean shutup_loop = true;
    do {
        System.out.println("Hey, I'm thread " + myID);
        System.out.println("Hey, I'm thread " + Thread.currentThread().getName());
        try {
            Thread.sleep(10);
        }
        catch (java.lang.InterruptedException e) {
            System.out.println("thread " + myID + ": " + e);
        }

        // Do if you want the printing to all match up on one line
        synchronized (this) {
            ByteArrayOutputStream baos = SendReceive(pollPacket);

            System.out.print(myID + ": ");
            if (baos != null) {
                printStuff(baos);
                System.out.println();
            }
            notify();
        }

    } while (shutup_loop);

    return "poller is finished";
}

这些Poller线程调用SendReceive(),它是Poller类的一部分:

public synchronized ByteArrayOutputStream SendReceive(byte[] toSend)
{
    System.out.println("START");
    System.out.println("SendReceive()1 " + myID);
    System.out.println("SendReceive()2 " + Thread.currentThread().getName());
    System.out.println("END");

    try {
        ds_out.write(toSend, 0, toSend.length);
        ds_out.flush();
    }
    catch (java.io.IOException e) {
        System.out.println("thread " + myID + ": " + e);
    }

    try {
        m_socket.setSoTimeout(200);       // <-- might need tweaking
    }
    catch (java.net.SocketException e) {
        System.out.println("thread " + myID + ": " + e);
    }

    ByteArrayOutputStream baos = null;
    try {
        baos = getResponse(ds_in);
    }
    catch (java.io.IOException e) {
        System.out.println("thread " + myID + ": " + e);
    }

    return baos;
}

因为这是一个同步方法,我希望输出类似于:

START
SendReceive()1 pool-1-thread-1
SendReceive()2 pool-1-thread-1
END

START
SendReceive()1 pool-1-thread-2
SendReceive()2 pool-1-thread-2
END

相反它正在做:

START
START
START
START
START
START
SendReceive()1 pool-1-thread-2
START
START
START
SendReceive()1 pool-1-thread-6
SendReceive()1 pool-1-thread-7
SendReceive()2 pool-1-thread-2
SendReceive()1 pool-1-thread-3
SendReceive()2 pool-1-thread-6
SendReceive()1 pool-1-thread-1
SendReceive()1 pool-1-thread-9
SendReceive()1 pool-1-thread-8
SendReceive()2 pool-1-thread-9
END
...

是什么给出了?

2 个答案:

答案 0 :(得分:2)

synchronized使用this作为锁:在您的情况下,您有几个Poller个实例,因此每个实例使用不同的锁。为了使它工作,你需要一个共同的锁:

  • 制作方法static
  • 或使用共同的private static final Object lock = new Object();并使用synchronized(lock) {...}

答案 1 :(得分:0)

如果你所追求的是在轮询器之间共享套接字,则不需要使用执行程序服务。您无论如何都需要序列化套接字的使用,因此您可以循环遍历轮询任务列表并将当前套接字交给套接字使用。

另一方面,如果你真的想要使用相同的套接字并行轮询,你的网络协议应该支持你,允许你发送一个轮询消息,而不必等待它的响应;你会有多个飞行请求。但我怀疑你要解决的问题是一个更大而且更不同的问题。