Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/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 ConcurrentHashMap在调用put方法时不插入非空键值对_Java_Multithreading_Concurrenthashmap_Socketchannel - Fatal编程技术网

Java ConcurrentHashMap在调用put方法时不插入非空键值对

Java ConcurrentHashMap在调用put方法时不插入非空键值对,java,multithreading,concurrenthashmap,socketchannel,Java,Multithreading,Concurrenthashmap,Socketchannel,我使用ConcurrentHashMap缓存我在SocketChannel上处理的任务。StreamTask是一个可运行的任务,用于在客户端-服务器通信期间超过往返阈值时重新调度自身,因此,如果时间流逝,它将从缓存中删除自身。此外,StreamWriteTask线程将把它放在缓存中,StreaReadTask将尝试删除它 问题是,当我调用“processingCache.put()”时,它并不总是添加到映射中 public class ClientServerTest { privat

我使用ConcurrentHashMap缓存我在SocketChannel上处理的任务。StreamTask是一个可运行的任务,用于在客户端-服务器通信期间超过往返阈值时重新调度自身,因此,如果时间流逝,它将从缓存中删除自身。此外,StreamWriteTask线程将把它放在缓存中,StreaReadTask将尝试删除它

问题是,当我调用“processingCache.put()”时,它并不总是添加到映射中

public class ClientServerTest {

    private class StreamTask implements Runnable {
        private final String taskIdentifier;
        private byte[] data;
        private int scheduleAttempts = 1;
        private long startTime;
        private Runnable future;

        private static final long ROND_TRIP_THRESHOLD = 15000L;
        private static final int MAX_SCHEDULE_ATTEMPTS = 3;

        public StreamTask(String taskIdentifier, byte[] data) {
            super();
            this.taskIdentifier = taskIdentifier;
            this.data = data;
        }

        @Override
        public void run() {
            if (scheduleAttempts < MAX_SCHEDULE_ATTEMPTS) {
                StreamTask task = null;
                processingCacheLock.writeLock().lock(); 
                try{
                    task = processingCache.remove(taskIdentifier);
                }finally{
                    processingCacheLock.writeLock().unlock();
                }

                if (task == null) {
                    return;
                }

                scheduleStreamTask(task);
                scheduleAttempts++;
            } else {
                failedTasks.add(this);
            }

        }

        @Override
        public int hashCode() {
            return taskIdentifier == null ? 0 : super.hashCode();
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }

            if (!(obj instanceof StreamTask)) {
                return false;
            }
            StreamTask task = (StreamTask) obj;
            boolean equals = false;
            if (this.taskIdentifier != null
                    && this.taskIdentifier.equals(task.taskIdentifier)) {
                equals = true;
            }

            if (this.hashCode() == task.hashCode()) {
                equals = true;
            }

            return equals;
        }

    }

    private class StreamWriteTask implements Runnable {
        private ByteBuffer buffer;
        private SelectionKey key;

        private StreamWriteTask(ByteBuffer buffer, SelectionKey key) {
            this.buffer = buffer;
            this.key = key;
        }

        private byte[] getData() {
            byte[] data;
            if (key.attachment() != null) {
                data = (byte[]) key.attachment();
                System.out.println("StreamWriteTask continuation.....");
            } else {
                StreamTask task = getStreamTask();
                if (task == null) {
                    return null;
                }
                System.out.println("Processing New Task ~~~~~ "
                        + task.taskIdentifier);
                processingCacheLock.readLock().lock();
                try {
                    task = processingCache.put(task.taskIdentifier, task);
                    boolean cached = processingCache.containsKey(task.taskIdentifier);
                    System.out.println("Has task been cached? " + cached);
                } finally {
                    processingCacheLock.readLock().unlock();
                }

                task.startTime = System.currentTimeMillis();
                data = task.data;
            }

            return data;
        }

        @Override
        public void run() {
            byte[] data = getData();
            if (data != null) {
                SocketChannel sc = (SocketChannel) key.channel();
                buffer.clear();
                buffer.put(data);
                buffer.flip();
                int results = 0;
                while (buffer.hasRemaining()) {
                    try {
                        results = sc.write(buffer);
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    if (results == 0) {
                        buffer.compact();
                        buffer.flip();
                        data = new byte[buffer.remaining()];
                        buffer.get(data);
                        key.interestOps(SelectionKey.OP_WRITE);
                        key.attach(data);
                        System.out
                                .println("Partial write to socket channel....");
                        selector.wakeup();
                        return;
                    }
                }
            }

            System.out
                    .println("Write to socket channel complete for client...");
            key.interestOps(SelectionKey.OP_READ);
            key.attach(null);
            returnBuffer(buffer);
            selector.wakeup();
        }

    }

    private class StreamReadTask implements Runnable {
        private ByteBuffer buffer;
        private SelectionKey key;

        private StreamReadTask(ByteBuffer buffer, SelectionKey key) {
            this.buffer = buffer;
            this.key = key;
        }

        @Override
        public void run() {
            long endTime = System.currentTimeMillis();
            SocketChannel sc = (SocketChannel) key.channel();
            buffer.clear();
            byte[] data = (byte[]) key.attachment();
            if (data != null) {
                buffer.put(data);
            }
            int count = 0;
            int readAttempts = 0;
            try {
                while ((count = sc.read(buffer)) > 0) {
                    readAttempts++;
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            if (count == 0) {
                buffer.flip();
                data = new byte[buffer.limit()];
                buffer.get(data);
                String uuid = new String(data);
                System.out.println("Client Read - uuid ~~~~ " + uuid);
                boolean success = finalizeStreamTask(uuid, endTime);
                key.interestOps(SelectionKey.OP_WRITE);
                key.attach(null);
                System.out.println("Did task finalize correctly ~~~~ "
                        + success);
            }

            if (count == -1) {
                try {
                    sc.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            returnBuffer(buffer);
            selector.wakeup();
        }

    }

    private class ClientWorker implements Runnable {

        @Override
        public void run() {
            try {

                while (selector.isOpen()) {
                    int count = selector.select(500);

                    if (count == 0) {
                        continue;
                    }

                    Iterator<SelectionKey> it = selector.selectedKeys()
                            .iterator();

                    while (it.hasNext()) {
                        final SelectionKey key = it.next();
                        it.remove();
                        if (!key.isValid()) {
                            continue;
                        }

                        if (key.isConnectable()) {
                            SocketChannel sc = (SocketChannel) key.channel();
                            if (!sc.finishConnect()) {
                                continue;
                            }
                            sc.register(selector, SelectionKey.OP_WRITE);
                        }

                        if (key.isReadable()) {
                            ByteBuffer buffer = borrowBuffer();
                            if (buffer != null) {
                                key.interestOps(0);
                                executor.execute(new StreamReadTask(buffer, key));
                            }
                        }
                        if (key.isWritable()) {
                            ByteBuffer buffer = borrowBuffer();
                            if (buffer != null) {
                                key.interestOps(0);
                                executor.execute(new StreamWriteTask(buffer,
                                        key));
                            }
                        }
                    }
                }
            } catch (IOException ex) {
                // Handle Exception
            }

        }
    }

    private class ServerWorker implements Runnable {
        @Override
        public void run() {
            try {
                Selector selector = Selector.open();
                ServerSocketChannel ssc = ServerSocketChannel.open();
                ServerSocket socket = ssc.socket();
                socket.bind(new InetSocketAddress(9001));
                ssc.configureBlocking(false);
                ssc.register(selector, SelectionKey.OP_ACCEPT);
                ByteBuffer buffer = ByteBuffer.allocateDirect(65535);
                DataHandler handler = new DataHandler();

                while (selector.isOpen()) {
                    int count = selector.select(500);

                    if (count == 0) {
                        continue;
                    }

                    Iterator<SelectionKey> it = selector.selectedKeys()
                            .iterator();

                    while (it.hasNext()) {
                        final SelectionKey key = it.next();
                        it.remove();
                        if (!key.isValid()) {
                            continue;
                        }

                        if (key.isAcceptable()) {
                            ssc = (ServerSocketChannel) key.channel();
                            SocketChannel sc = ssc.accept();
                            sc.configureBlocking(false);
                            sc.register(selector, SelectionKey.OP_READ);
                        }
                        if (key.isReadable()) {
                            handler.readSocket(buffer, key);
                        }
                        if (key.isWritable()) {
                            handler.writeToSocket(buffer, key);
                        }
                    }
                }

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    private class DataHandler {

        private JsonObject parseData(StringBuilder builder) {
            if (!builder.toString().endsWith("}")) {
                return null;
            }

            JsonParser parser = new JsonParser();
            JsonObject obj = (JsonObject) parser.parse(builder.toString());
            return obj;
        }

        private void readSocket(ByteBuffer buffer, SelectionKey key)
                throws IOException {
            SocketChannel sc = (SocketChannel) key.channel();
            buffer.clear();
            int count = Integer.MAX_VALUE;
            int readAttempts = 0;
            try {
                while ((count = sc.read(buffer)) > 0) {
                    readAttempts++;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (count == 0) {
                buffer.flip();
                StringBuilder builder = key.attachment() instanceof StringBuilder ? (StringBuilder) key
                        .attachment() : new StringBuilder();
                Charset charset = Charset.forName("UTF-8");
                CharsetDecoder decoder = charset.newDecoder();
                decoder.onMalformedInput(CodingErrorAction.IGNORE);
                CharBuffer charBuffer = decoder.decode(buffer);
                String content = charBuffer.toString();
                charBuffer = null;
                builder.append(content);
                JsonObject obj = parseData(builder);
                if (obj == null) {
                    // System.out.println("Server processed partial read for task");
                    key.attach(builder);
                    key.interestOps(SelectionKey.OP_READ);
                } else {
                    JsonPrimitive uuid = obj.get("uuid").getAsJsonPrimitive();
                    System.out
                            .println("Server read complete for task  ~~~~~~~ "
                                    + uuid);
                    key.attach(uuid.toString().getBytes());
                    key.interestOps(SelectionKey.OP_WRITE);
                }
            }

            if (count == -1) {
                key.attach(null);
                sc.close();
            }
        }

        private void writeToSocket(ByteBuffer buffer, SelectionKey key)
                throws IOException {
            SocketChannel sc = (SocketChannel) key.channel();
            byte[] data = (byte[]) key.attachment();
            buffer.clear();
            buffer.put(data);
            buffer.flip();
            int writeAttempts = 0;
            while (buffer.hasRemaining()) {
                int results = sc.write(buffer);
                writeAttempts++;
                // System.out.println("Write Attempt #" + writeAttempts);
                if (results == 0) {
                    System.out.println("Server process partial write....");
                    buffer.compact();
                    buffer.flip();
                    data = new byte[buffer.remaining()];
                    buffer.get(data);
                    key.attach(data);
                    key.interestOps(SelectionKey.OP_WRITE);
                    return;
                }
            }

            System.out.println("Server write complete for task ~~~~~ "
                    + new String(data));
            key.interestOps(SelectionKey.OP_READ);
            key.attach(null);
        }
    }

    public ClientServerTest() throws IOException {
        selector = Selector.open();
        processingCache = new ConcurrentHashMap<String, StreamTask>(
                MAX_DATA_LOAD, 2);
        for (int index = 0; index < MAX_DATA_LOAD; index++) {
            JsonObject obj = new JsonObject();
            String uuid = UUID.randomUUID().toString();
            obj.addProperty("uuid", uuid);
            String data = RandomStringUtils.randomAlphanumeric(12800000);
            obj.addProperty("event", data);
            StreamTask task = new StreamTask(uuid, obj.toString().getBytes());
            taskQueue.add(task);
        }

        for (int index = 0; index < CLIENT_SOCKET_CONNECTIONS; index++) {
            ByteBuffer bf = ByteBuffer.allocate(2 << 23);
            bufferQueue.add(bf);
            SocketChannel sc = SocketChannel.open();
            sc.configureBlocking(false);
            sc.connect(new InetSocketAddress("127.0.0.1", 9001));
            sc.register(selector, SelectionKey.OP_CONNECT);
        }

        Thread serverWorker = new Thread(new ServerWorker());
        serverWorker.start();

        Thread clientWorker = new Thread(new ClientWorker());
        clientWorker.start();

    }

    private void start() {
        long startTime = System.currentTimeMillis();
        for (;;) {
            if (taskQueue.isEmpty() && processingCache.isEmpty()) {
                long endTime = System.currentTimeMillis();
                System.out.println("Overall Processing time ~~~~ "
                        + (endTime - startTime) + "ms");
                break;
            }
        }
    }

    private ByteBuffer borrowBuffer() {
        ByteBuffer buffer = null;

        try {
            buffer = bufferQueue.poll(5000L, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return buffer;
    }

    private boolean returnBuffer(ByteBuffer buffer) {
        boolean success = true;
        try {
            buffer.clear();
            bufferQueue.offer(buffer, 5000L, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            success = false;
            e.printStackTrace();
        }
        return success;
    }

    private StreamTask getStreamTask() {
        StreamTask task = null;
        taskQueueAddLock.lock();
        try {
            task = taskQueue.take();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            taskQueueAddLock.unlock();
        }

        return task;
    }

    private boolean scheduleStreamTask(StreamTask task) {
        boolean success = true;
        taskQueueRemoveLock.lock();
        try {
            taskQueue.offer(task, 5000L, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            success = false;
            e.printStackTrace();
        } finally {
            taskQueueRemoveLock.unlock();
        }

        return success;
    }

    private boolean finalizeStreamTask(String uuid, long endTime) {
        boolean success = true;
        StreamTask task;
        processingCacheLock.writeLock().lock();
        try {
            task = processingCache.remove(uuid);
            success = task != null;
        } finally {
            processingCacheLock.writeLock().unlock();
        }

        if (success) {
            success = executor.remove(task.future);
            executor.purge();
        }

        if (!success) {
            taskQueueAddLock.lock();
            taskQueueRemoveLock.lock();
            try {
                Iterator<StreamTask> it = taskQueue.iterator();
                while (it.hasNext()) {
                    task = it.next();
                    if (task.taskIdentifier == uuid) {
                        it.remove();
                        success = true;
                    }
                }
            } finally {
                taskQueueAddLock.unlock();
                taskQueueRemoveLock.unlock();
            }
            success = !taskQueue.contains(task);
        }

        System.out.println("Processing time ~~~~~~ "
                + (endTime - task.startTime) + "ms");
        return success;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            ClientServerTest test = new ClientServerTest();
            test.start();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private static final int CLIENT_SOCKET_CONNECTIONS = 1;
    private static final int MAX_DATA_LOAD = 2;

    private volatile ConcurrentHashMap<String, StreamTask> processingCache;
    private volatile LinkedBlockingQueue<StreamTask> taskQueue = new LinkedBlockingQueue<StreamTask>();
    private volatile ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(
            CLIENT_SOCKET_CONNECTIONS);
    private volatile LinkedBlockingQueue<ByteBuffer> bufferQueue = new LinkedBlockingQueue<ByteBuffer>();
    private volatile List<StreamTask> failedTasks = new ArrayList<StreamTask>();
    private volatile Selector selector;
    private final ReentrantLock taskQueueAddLock = new ReentrantLock();
    private final ReentrantLock taskQueueRemoveLock = new ReentrantLock();
    private final ReentrantReadWriteLock processingCacheLock = new ReentrantReadWriteLock();
}
公共类ClientServerTest{
私有类StreamTask实现可运行{
私有最终字符串标识符;
专用字节[]数据;
私有int scheduleAttempts=1;
私人长启动时间;
私人经营的未来;
专用静态最终长行程行程阈值=15000L;
专用静态最终int最大计划尝试次数=3;
公共StreamTask(字符串taskIdentifier,字节[]数据){
超级();
this.taskIdentifier=任务标识符;
这个数据=数据;
}
@凌驾
公开募捐{
if(调度尝试次数<最大调度尝试次数){
StreamTask任务=null;
processingCacheLock.writeLock().lock();
试一试{
task=processingCache.remove(taskIdentifier);
}最后{
正在处理CacheLock.writeLock().unlock();
}
如果(任务==null){
返回;
}
调度任务(任务);
schedule++;
}否则{
失败的任务。添加(此);
}
}
@凌驾
公共int hashCode(){
return taskIdentifier==null?0:super.hashCode();
}
@凌驾
公共布尔等于(对象obj){
if(obj==null){
返回false;
}
如果(!(流任务的obj实例)){
返回false;
}
StreamTask任务=(StreamTask)obj;
布尔等于假;
如果(this.taskIdentifier!=null
&&this.taskIdentifier.equals(task.taskIdentifier)){
等于等于真;
}
if(this.hashCode()==task.hashCode()){
等于等于真;
}
回报相等;
}
}
私有类StreamWriteTask实现可运行{
专用字节缓冲区;
私钥;
专用StreamWriteTask(ByteBuffer缓冲区,SelectionKey密钥){
this.buffer=缓冲区;
this.key=key;
}
专用字节[]getData(){
字节[]数据;
if(key.attachment()!=null){
数据=(字节[])键。附件();
System.out.println(“StreamWriteTask continuation…”);
}否则{
StreamTask任务=getStreamTask();
如果(任务==null){
返回null;
}
System.out.println(“处理新任务~
+任务标识符);
正在处理cachelock.readLock().lock();
试一试{
task=processingCache.put(task.taskIdentifier,task);
布尔缓存=processingCache.containsKey(task.taskIdentifier);
System.out.println(“任务是否已缓存?”+缓存);
}最后{
正在处理cachelock.readLock().unlock();
}
task.startTime=System.currentTimeMillis();
data=task.data;
}
返回数据;
}
@凌驾
公开募捐{
字节[]数据=getData();
如果(数据!=null){
SocketChannel sc=(SocketChannel)key.channel();
buffer.clear();
buffer.put(数据);
flip();
int结果=0;
while(buffer.haslaining()){
试一试{
结果=sc.write(缓冲区);
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
如果(结果==0){
buffer.compact();
flip();
数据=新字节[buffer.remaining()];
buffer.get(数据);
key.interesttops(选择key.OP_WRITE);
键。附上(数据);
系统输出
.println(“部分写入套接字通道…”);
selector.wakeup();
返回;
}
}
}
系统输出
.println(“客户端写入套接字通道完成…”);
key.interesttops(选择key.OP_READ);
key.attach(空);
返回缓冲区(缓冲区);
selector.wakeup();
}
}
私有类StreamReadTask实现可运行{
专用字节缓冲区;
私钥;
私有StreamReadTask(ByteBuffer缓冲区,SelectionKey){
this.buffer=缓冲区;
this.key=key;
}
@凌驾
公开募捐{
long-endTime=System.currentTimeMillis();
SocketChannel sc=(SocketChannel)key.channel();
buffer.clear();
字节[]数据=(字节[])键。附件();
如果(数据!=null){
buffer.put(数据);
}
整数计数=0;
int readtruments=0;
试一试{
task = processingCache.put(task.taskIdentifier, task);
boolean cached = processingCache.containsKey(task.taskIdentifier);