Hello in my exercise I need to show resource access problems with multi threads.
I need to increment indexes of shared (between threads) int table called histogramTable[]the size of table is known, and data is in file. Each thread got it own range, called interval. For example: I have 4 threads and every threads getting the following indexes:
Thread 1: 0 - 1_000_000
Thread 2: 1_000_000 - 2_000_000
Thread 3: 2_000_000 - 3_000_000
Thread 4: 3_000_000 - 4_000_000
And here is my problem, once you start a program with given number on threads, it's threadsNumber variable, it seems that only one thread is running. Because sum of bytes is always tabSize / threadsNumber. For above example it's 1_000_000 bytes.
With problem of thread access it should be 3_800_000 - 4_000_000 bytes. Can you tell me what I'm doing wrong?
I'm giving you whole code cause in my opinion its short. Also there is a commented out funcion called randomizeBytes() to fastly generate byte file.   
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");
    }
}