Jas*_*key 12 java multithreading
我知道答案是没有,这里有一个例子,为什么单线程比Java的多线程更快?.
因此,当在线程中处理任务是微不足道的时,创建线程的成本将比分发任务产生更多的开销.这是一个单线程比多线程更快的情况.
是否有更多情况下单个线程比多线程更快?
我们什么时候应该决定放弃多线程,只使用一个线程来实现我们的目标?
虽然问题标记为java,但也欢迎在Java之外进行讨论.如果我们能在答案中有一个小例子来解释,那将会很棒.
Jen*_*ack 11
这是一个关于线程及其与实际工作的链接的非常好的问题,这意味着可用的物理CPU及其核心和超线程.
因此,我从高度并行的多线程中学到的经验是:
这里有一个小程序(javafx)可以玩.它:
使用MacPro(4核)导致:
更改计数方式,例如递增共享整数(AtomicInteger或synchronized)将极大地改变许多线程的性能.
public class MulithreadingEffects extends Application {
static class ParallelProgressBar extends ProgressBar {
AtomicInteger myDoneCount = new AtomicInteger();
int myTotalCount;
Timeline myWhatcher = new Timeline(new KeyFrame(Duration.millis(10), e -> update()));
BooleanProperty running = new SimpleBooleanProperty(false);
public void update() {
setProgress(1.0*myDoneCount.get()/myTotalCount);
if (myDoneCount.get() >= myTotalCount) {
myWhatcher.stop();
myTotalCount = 0;
running.set(false);
}
}
public boolean isRunning() { return myTotalCount > 0; }
public BooleanProperty runningProperty() { return running; }
public void start(int totalCount) {
myDoneCount.set(0);
myTotalCount = totalCount;
setProgress(0.0);
myWhatcher.setCycleCount(Timeline.INDEFINITE);
myWhatcher.play();
running.set(true);
}
public void add(int n) {
myDoneCount.addAndGet(n);
}
}
int mySize = 100000000;
byte[] inData = new byte[mySize];
ParallelProgressBar globalProgressBar = new ParallelProgressBar();
BooleanProperty iamReady = new SimpleBooleanProperty(false);
AtomicInteger myCounter = new AtomicInteger(0);
void count(int start, int step) {
new Thread(""+start){
public void run() {
int count = 0;
int loops = 0;
for (int i = start; i < mySize; i+=step) {
for (int m = 0x80; m > 0; m >>=1) {
if ((inData[i] & m) > 0) count++;
}
if (loops++ > 99) {
globalProgressBar.add(loops);
loops = 0;
}
}
myCounter.addAndGet(count);
globalProgressBar.add(loops);
}
}.start();
}
void pcount(Label result, int n) {
result.setText("("+n+")");
globalProgressBar.start(mySize);
long start = System.currentTimeMillis();
myCounter.set(0);
globalProgressBar.runningProperty().addListener((p,o,v) -> {
if (!v) {
long ms = System.currentTimeMillis()-start;
result.setText(""+ms+" ms ("+myCounter.get()+")");
}
});
for (int t = 0; t < n; t++) count(t, n);
}
void testParallel(VBox box) {
HBox hbox = new HBox();
Label result = new Label("-");
for (int i : new int[]{1, 2, 4, 8}) {
Button run = new Button(""+i);
run.setOnAction( e -> {
if (globalProgressBar.isRunning()) return;
pcount(result, i);
});
hbox.getChildren().add(run);
}
hbox.getChildren().addAll(result);
box.getChildren().addAll(globalProgressBar, hbox);
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("ProgressBar's");
globalProgressBar.start(mySize);
new Thread("Prepare"){
public void run() {
iamReady.set(false);
Random random = new Random();
random.setSeed(4711);
for (int i = 0; i < mySize; i++) {
inData[i] = (byte)random.nextInt(256);
globalProgressBar.add(1);
}
iamReady.set(true);
}
}.start();
VBox box = new VBox();
Scene scene = new Scene(box,400,80,Color.WHITE);
primaryStage.setScene(scene);
testParallel(box);
GUIHelper.allowImageDrag(box);
primaryStage.show();
}
public static void main(String[] args) { launch(args); }
}
Run Code Online (Sandbox Code Playgroud)
并非所有算法都可以并行处理(严格顺序的算法;其中Amdahl定律中P = 0 )或至少不能有效(参见P-complete).其他算法更适合并行执行(极端情况称为"令人尴尬的并行").
与类似的顺序算法相比,并行算法的简单实现在复杂性或空间方面可能效率较低.如果没有明显的方法来并行化算法以使其获得加速,那么您可能需要选择另一个类似的并行算法来解决相同的问题但可能效率更高或更低.如果忽略线程/进程创建和直接进程间通信开销,则在使用IO瓶颈等共享资源或由较高内存消耗引起的增加分页时,仍可能存在其他限制因素.
我们什么时候应该决定放弃多线程,只使用一个线程来实现我们的目标?
在单线程和多线程之间进行决策时,应考虑更改实现所需的时间以及开发人员增加的复杂性.如果使用多个线程只有很小的增益,你可能会认为通常由多线程应用程序引起的增加的维护成本不值得加速.
归档时间: |
|
查看次数: |
10470 次 |
最近记录: |