提问者:小点点

使线程并发运行而不是顺序运行的问题


目前我正在做一个项目,我必须使用threadsblockingqueue来制作简单的程序:

该程序是凯撒编码,为什么LinkedBlockingQueue很好,因为它是一个赋值:)。

程序应从控制台读取字母(包括回车和换行char(10)char(13)),这将作为标识未编码字母结束的标志!

因此队列看起来如下所示(假设移位因子为3):

  • ['a'->'a'->'a'->'13'->d'->d'->d']
  • 然后,在对正在读取的字母进行编码时,这些字母将被写入并从队列中删除。

我管理使程序与线程一起工作,这些线程按顺序运行,但它应该并发运行:

所以我做了以下的事情:

代码:

import java.io.*;
import java.util.concurrent.*;


public class Caesar {

    private final static int CR = 13,LF=10, SHIFT_FACTOR=3, OFFSET=23;

    public static void main(String[] args) throws InterruptedException {
        var br = new BufferedReader(new InputStreamReader(System.in));
        var letters = new LinkedBlockingQueue<Character>();

        Thread t1= new Thread(()-> takeInput(letters,br));
        Thread t2= new Thread(()-> {
            try {
                encode(letters);
            } catch (InterruptedException e) {e.printStackTrace();}
        });
        Thread t3 = new Thread(()-> send(letters));

        t1.start();
        t1.join();
        t2.start();
        t2.join();
        t3.start();
        t3.join();
    }

    private static void takeInput(BlockingQueue<Character>letters, BufferedReader br ) {
        System.out.println("Enter your input!.");
        int temp;

        try {
            while((temp=br.read())!=-1) {
                letters.offer((char) temp);
                if (temp == CR || temp == LF){
                    //continue; //for multi-line function to be cancelled by ctr+d !.
                    break;
                }
            }
        }catch (IOException e){ e.printStackTrace(); }
        finally {
            try {
                br.close();
            } catch (IOException e) { e.printStackTrace(); }
        }
    }

    private static void encode( BlockingQueue<Character>letters) throws InterruptedException {
        System.out.println("started encoding");
        Character toEncode;
        for (Character temp : letters) {
             toEncode=letters.take();
            assert toEncode!=null;
            if (toEncode == ' ' || toEncode == '.'){
                letters.add(toEncode);
            }else if (toEncode == CR ||toEncode ==LF){
                letters.add(toEncode);
                break;
            }else if (cap(temp) < 'X') {
                letters.add((char)(temp+SHIFT_FACTOR));
            }else{
                letters.add((char)(temp - OFFSET));
            }
        }
    }

    private static Character cap(Character temp) {
        return temp >= 'a' ? Character.toUpperCase(temp):temp;//ternary operator see https://en.wikipedia.org/wiki/%3F:
    }
    private static void send( BlockingQueue<Character> letters){
        System.out.print("the encoded elements are : -> ");
        letters.forEach(temp-> System.out.print(temp.toString()));//require java 8 and above!
    }
}

输出量

Enter your input!.
aaaa
started encoding
the encoded elements are : -> dddd

代码工作正常,但不并发:

使

t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join(); 

会使程序行为错误!。

输出错误!

Enter your input!.
the encoded elements are : -> started encoding
aaa
(program stopped without putting nor adding anything)

教授给了我们一个GO代码,用它作为参照能够实现的功能:

这里有一个链接,指向pastebin上的go代码

你可以随意提出任何建议:)


共1个答案

匿名用户

    t1.start();
    t1.join();
    t2.start();
    t2.join();
    t3.start();
    t3.join();

启动一个线程,然后等待它完成,然后再启动下一个线程。

将所有连接放在开始之后:

    t1.start();
    t2.start();
    t3.start();
    t1.join();
    t2.join();
    t3.join();