java实现golang类似的chan

Posted 吴冬冬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java实现golang类似的chan相关的知识,希望对你有一定的参考价值。

java版本的CSP操作

public class Chan<T> 
    private T message;

    private boolean empty = true;

    public synchronized T take() 
        while (empty) 
            try 
                wait();
             catch (InterruptedException e) 
            
        
        empty = true;
        notifyAll();
        return message;
    

    public synchronized void put(T message) 
        while (!empty) 
            try 
                wait();
             catch (InterruptedException e) 
            
        
        empty = false;
        this.message = message;
        notifyAll();
    

基本的csp操作上面就可以了,但是如果想实现golang的select模型,就要对消息进行改造一下:

class ChanMessage<T> 
    private String type;
    private T data;

    public ChanMessage(String type, T data) 
        this.type = type;
        this.data = data;
    


    public String getType() 
        return type;
    

    public void setType(String type) 
        this.type = type;
    

    public T getData() 
        return data;
    

    public void setData(T data) 
        this.data = data;
    




public class Chan<T extends ChanMessage> 
    private T message;

    private boolean empty = true;

    public synchronized T take() 
        while (empty) 
            try 
                wait();
             catch (InterruptedException e) 
            
        
        empty = true;
        notifyAll();
        return message;
    

    public synchronized void put(T message) 
        while (!empty) 
            try 
                wait();
             catch (InterruptedException e) 
            
        
        empty = false;
        this.message = message;
        notifyAll();
    


    public static void main(String[] args) 

        Chan<ChanMessage<Integer>> chanMessageChan = new Chan<>();


        new Thread(() -> 
            chanMessageChan.put(new ChanMessage<>("timeout", new Integer(1)));
        ).start();


        new Thread(() -> 
            ChanMessage<Integer> chanMessage = chanMessageChan.take();
            switch (chanMessage.getType()) 
                case "timeout":
                    System.out.println(chanMessage.getData());
                    break;
                default:
                    break;

            
        ).start();
    

那么具有缓存的chan当然也好实现了

public class Chan<T extends ChanMessage> 

    private List<T> lists = new ArrayList<>();

    private int size;

    public Chan(int size) 
        this.size = size;
    


    public synchronized T take() 
        while (lists.size() == 0) 
            try 
                wait();
             catch (InterruptedException e) 
            
        
        T message = lists.remove(0);
        notifyAll();
        return message;
    

    public synchronized void put(T message) 
        while (lists.size() >= size) 
            try 
                wait();
             catch (InterruptedException e) 
            
        
        lists.add(message);
        notifyAll();
    
 

来,我们用超时退出试下chan的复用

public static void main(String[] args) 
        Chan<ChanMessage<Integer>> chanMessageChan = new Chan<>(1);

        new Thread(() -> 
            chanMessageChan.put(new ChanMessage<>("success", new Integer(1)));

            chanMessageChan.put(new ChanMessage<>("success", new Integer(2)));
        ).start();

        new Thread(() -> 
            try 
                Thread.sleep(1000);
             catch (InterruptedException e) 
                e.printStackTrace();
            
            chanMessageChan.put(new ChanMessage<>("timeout", new Integer(0)));
        ).start();
        new Thread(() -> 
            while (true) 
                ChanMessage<Integer> chanMessage = chanMessageChan.take();
                switch (chanMessage.getType()) 
                    case "success":
                        System.out.println(chanMessage.getData());
                        break;
                    case "timeout":
                        return;
                    default:
                        break;

                
            
        ).start();
    

对于追求完美的人来说,不介意加点语法糖

 	static void go(Runnable runnable) 
        new Thread(runnable).start();
    


    public static void main(String[] args) 
        Chan<ChanMessage<Integer>> chanMessageChan = new Chan<>(1);

        go(() -> 
            chanMessageChan.put(new ChanMessage<>("success", new Integer(1)));

            chanMessageChan.put(new ChanMessage<>("success", new Integer(2)));
        );

        go(() -> 
            try 
                Thread.sleep(1000);
             catch (InterruptedException e) 
                e.printStackTrace();
            
            chanMessageChan.put(new ChanMessage<>("timeout", new Integer(0)));
        );
        go(() -> 
            while (true) 
                ChanMessage<Integer> chanMessage = chanMessageChan.take();
                switch (chanMessage.getType()) 
                    case "success":
                        System.out.println(chanMessage.getData());
                        break;
                    case "timeout":
                        return;
                    default:
                        break;

                
            
        );
    

至此就用java实现了golang的select操作,写完这段代码有种打通了任督二脉的感觉,语言不再是障碍

以上是关于java实现golang类似的chan的主要内容,如果未能解决你的问题,请参考以下文章

Golang:我可以转换为 chan 接口

Go语言无锁队列组件的实现 (chan/interface/select)

在Golang中实现有无限容量的同步Queue

Golang: chan定义问题

Golang 中的指针 - Pointer

golang 小知识-持续更新中