Java多线程大写字符串

时间:2018-10-31 18:11:08

标签: java multithreading

我有一个字符串:“ abcdef”,还有3个线程:t1,t2和t3。我希望他们返回大写的字符串:“ ABCDEF”(字符的顺序无关紧要)。我设法将字符串大写3次。我希望这一切只发生一次。这是主要的类:

public static void main(String[] args) {
    Thread t1 = new Thread(new CapitalizeString("Thread 1", "abcdef"));
    Thread t2 = new Thread(new CapitalizeString("Thread 2", "abcdef"));
    Thread t3 = new Thread(new CapitalizeString("Thread 3", "abcdef"));

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

}

这是用于大写的类:

import java.util.Random;

public class CapitalizeString implements Runnable {
String list;
String nameThread;

public CapitalizeString(String name, String str) {
    nameThread = name;
    list = str;
}

public void capitalize() {
    char[] arr = list.toCharArray();

    for (int i = 0; i < list.length(); i++) {
        arr[i] = Character.toUpperCase(arr[i]);
        System.out.println("Thread-ul " + nameThread + " solved " + arr[i]);
    }
    System.out.print("\n");
}

@Override
public void run() {
    try {
        capitalize();
    } catch (Exception e) {
    }
}
}

3 个答案:

答案 0 :(得分:3)

这不仅复杂得多,而且速度慢了许多倍。但是,作为练习,我建议使用最简单的方法,即使用parallelStream

String upper = "abcdef".chars().parallel()
        .map(Character::toUpperCase)
        .mapToObj(c -> Character.toString((char) c))
        .collect(Collectors.joining());
System.out.println(upper);

您可能想知道,为什么速度这么慢?从人的角度考虑,您可以

a)用手在纸上转换字母,或者

b)您可以向三个朋友发送三个字母,要求他们分别向您发送两个大写字母。

除了更糟糕的是,因为必须先启动线程,这甚至会花费更长的时间,

c)找到三个愿意回答您信件的新朋友,然后b)

答案 1 :(得分:0)

注意:对于短字符串,仅使用String str = "abcdef".toUpperCase();会更快(在我的计算机上,当字符串长于〜50000个字符时,多线程代码开始更快地工作)。

该字符串被拆分为一个char数组(chars)。每个线程迭代遍历数组chars,将一个字母转换为大写,并跳过2个字母以供其他线程处理。完成所有线程后,该数组将变回String

public static void main(String args[]) {

    String str = "abcdef";
    System.out.println(str);
    char[] chars = str.toCharArray();

    Thread t1 = new Thread(new CapitalizeString(chars, 0, 3));
    Thread t2 = new Thread(new CapitalizeString(chars, 1, 3));
    Thread t3 = new Thread(new CapitalizeString(chars, 2, 3));

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

    // wait until all threads finish their work
    try{
        t1.join();
        t2.join();
        t3.join();
    }catch(InterruptedException e){ }

    // print the result
    str = String.valueOf(chars);
    System.out.println(str);
}

CapitalizeString类:

public class CapitalizeString implements Runnable {

    char[] chars;
    int start;
    int numThreads;

    public CapitalizeString(char[] chars, int startIndex, int numThreads) {
        this.chars = chars;
        this.numThreads = numThreads;
        start = startIndex;
    }

    @Override
    public void run() {
        for(int x = start; x < chars.length; x += numThreads){
            chars[x] = Character.toUpperCase(chars[x]);
        }
    }
}

答案 2 :(得分:0)

是的,我第一次回答后,这个问题就被修改了,现在已经有了一个可以接受的答案,但是我还是想发表评论。这可能被认为是一个更完整的示例,因为CapitalizeWorker类正在从CapitalizeJob类开始工作并放回结果。我认为这是一个更好的示例,因为它不依赖特定数量的线程,而是针对系统拥有的许多内核进行了优化。它还正在关闭并以干净的方式等待结果。只是我的价值$ .02。

private void run() throws InterruptedException {
    CapitalizeJob capitalizeJob = new CapitalizeJob("abcdef");
    int processors = Runtime.getRuntime().availableProcessors();
    ExecutorService executors = Executors.newFixedThreadPool(processors);
    for ( int t = 0; t < processors; ++t) {
        executors.execute(new CapitalizeWorker(capitalizeJob));
    }
    executors.shutdown(); // this is missing from OP thread example
    executors.awaitTermination(10, TimeUnit.SECONDS);
    System.out.println( capitalizeJob.getResult() );
}

public class CapitalizeWorker implements Runnable {
    private CapitalizeJob capitalizeJob;
    CapitalizeWorker(CapitalizeJob capitalizeJob) {
        this.capitalizeJob = capitalizeJob;
    }
    @Override
    public void run() {
        char c;
        while ( (c = capitalizeJob.getNextChar()) != 0 ) {
            System.out.println(Thread.currentThread().toString());
            capitalizeJob.setNextChar(Character.toUpperCase(c));
        }
    }
}
public class CapitalizeJob {
    private char[] arr;
    private int jobIndex;
    private char[] result;
    private int resultIndex;

    public CapitalizeJob(String name) {
        arr = name.toCharArray();
        result = new char[arr.length];
        jobIndex = 0;
        resultIndex = 0;
    }
    public synchronized char getNextChar() {
        return jobIndex < arr.length ? arr[jobIndex++] : 0 ;
    }
    public synchronized void setNextChar(char c) {
        result[resultIndex++] = c;
    }
    public String getResult() {
        return new String(result);
    }
}