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