在Java中启动多个线程

9 浏览
0 Comments

在Java中启动多个线程

在我的练习中,我需要展示多线程下的资源访问问题。我需要递增共享的(在线程之间共享的)名为histogramTable[]int类型表的索引,表的大小已知,数据存储在文件中。每个线程都有自己的范围,称为interval。例如:我有4个线程,每个线程获取以下索引:

线程1:0 - 1_000_000

线程2:1_000_000 - 2_000_000

线程3:2_000_000 - 3_000_000

线程4:3_000_000 - 4_000_000

我遇到的问题是,一旦使用给定数量的线程启动程序,即变量threadsNumber,似乎只有一个线程在运行。因为字节的总和始终为tabSize / threadsNumber。对于上述示例,它是1_000_000字节。根据线程访问的问题,它应该是3_800_000 - 4_000_000字节。你能告诉我我做错了什么吗?

我给你整个代码,因为我认为它很简短。还有一个被注释掉的名为randomizeBytes()的函数,用于快速生成字节文件。

Ex.java

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Ex2 {
    private static int threadsNumber = 4, tabSize = 4000000;
    public static int threadsCounter;
    public static byte[] dataTab = loadBytes();
    public static byte[] loadBytes() {
        byte data[] = new byte[tabSize];
        Path path = Paths.get("dane.txt");
        try {
            data = Files.readAllBytes(path);
        } 
        catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }
    /*private byte[] randomizeBytes() {
        Path path = Paths.get("binaryData.txt");
        byte bytes[] = new byte[tabSize];
        new Random().nextBytes(bytes);
        try {
            Files.write(path, bytes);
        } catch (IOException e) { 
            e.printStackTrace();
        }
        return bytes;
    }*/
    public static void runThreads(){
        threadsCounter = threadsNumber;
        int interval = tabSize / threadsNumber;
        int endIndex = 0;
        Thread[] threads = new Thread[threadsNumber];
        MyThread w;
        for(int i = 0 ; i < threadsNumber  ; i ++){
            endIndex = (i + 1) * interval;
            if(endIndex >= tabSize) 
                endIndex = tabSize;
            w = new MyThread(interval * i , endIndex);
            threads[i] = new Thread(w);
            threads[i].start();
            if(threads[i].isAlive())
                System.out.println("Thread number: " + i + " started and alive, indexes: " + interval*i + " - " + endIndex );
        }    
    }
    public synchronized static int decrementThreads(){
        return --threadsCounter;
    }
    public static void main(String args[]){
        runThreads();
    }
}

MyTherad.java

public class MyThread implements Runnable{
    private byte table[] = Ex2.dataTab;
    int startIndex,endIndex,temp;
    private int histogramTable[] = new int[256] ;
    private long timeStart, timeStop;
    public MyThread(int startIndex, int endIndex){
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }
    @Override
    public void run() { 
        timeStart = System.currentTimeMillis();
        for(int i = startIndex ; i < endIndex ; i ++) {
            temp = Byte.toUnsignedInt(table[i]);
            histogramTable[temp]++;
        }           
        timeStop = System.currentTimeMillis();
        System.out.println("Threads working: " + Ex2.threadsCounter);
        if(Ex2.decrementThreads() == 0) printSummary();
    }
    public void printSummary() {
        int sum = 0;
        for(int i : histogramTable) System.out.print(i + " ");
        System.out.println();
        for(int i = 0 ; i < 256 ; i ++)
            sum += histogramTable[i];
        System.out.println("Bytes: " + sum);
        System.out.println("Task complete in: " +  (timeStop - timeStart) + "ms");
    }
}

0
0 Comments

Java中启动多个线程的方式有很多种,但有时候我们可能会遇到问题,比如线程执行的顺序不符合我们的期望。那么这个问题是怎么出现的呢?该如何解决呢?

在Java中,我们可以使用Thread类的join()方法来解决这个问题。join()方法的作用是使调用该方法的线程等待被调用线程执行完毕。

下面是一个使用join()方法的示例代码:

Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        // 线程1的任务
    }
});
Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
        // 线程2的任务
    }
});
t1.start();
t1.join(); // 等待线程1执行完毕
t2.start();

在上面的代码中,我们首先创建了两个线程t1和t2,并分别给它们分配了任务。然后我们先启动线程t1,并调用t1.join()方法,这会使当前线程(通常是主线程)等待线程t1执行完毕。当t1执行完毕后,才会继续执行后面的代码。

通过使用join()方法,我们可以保证线程的执行顺序符合我们的期望。在上面的示例中,线程t2会在线程t1执行完毕后启动,从而实现了我们想要的效果。

如果没有使用join()方法,那么线程t1和线程t2的执行顺序是不确定的,可能会出现t2先执行的情况。

总结一下,通过使用Thread类的join()方法,我们可以解决多线程执行顺序不符合期望的问题。只需要在需要等待的线程上调用join()方法,即可保证该线程执行完毕后再继续执行后面的代码。

希望本文对你理解Java中多线程的概念和join()方法有所帮助。如果你想了解更多关于Java多线程的知识,可以参考这篇Java Multithreading concept and join() method上的回答。

0