我有一个字符串:“ 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) {
}
}
}
答案 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);
}
}