有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程Java:线程顺序

下面的代码发现输出结果不是顺序,不是从小到大,如何保证它是从小到大的顺序

java代码

public class TestSync {  

    /** 
     * @param args 
     */  
    public static void main(String[] args) {  
        for (int i = 0; i < 10; i++) {  
            new Thread(new Thread1()).start();  
        }  

    }  

    public int getNum(int i) {  
        synchronized (this) {  
            i++;  
        }  
        return i;  
    }  

    static class Thread1 implements Runnable {  
        static Integer value = 0;  
        @Override  
        public void run() {  
            TestSync ts = new TestSync();  
            value = ts.getNum(value);  
            System.out.println("thread1:" + value);  
        }  
    }  

}  

共 (3) 个答案

  1. # 1 楼答案

    更不用说,无法保证在线程中运行时会执行什么顺序代码。这是由所谓的时间限制造成的。CPU将为特定线程分配“片”时间。当切片启动时,它会有效地暂停线程,并允许其他线程获得切片。最终,它将返回暂停的线程,并为它们提供额外的时间片,但这实际上取决于CPU

    拥有多个内核和/或超线程允许CPU同时拥有更多线程

    然而,正如我所说的,不能保证线程的顺序是分时间的,每个线程何时何地暂停并恢复

    这意味着“i++”操作(以及相关打印)的完成顺序不一定是线程的启动顺序。此外,线程之间的任何共享变量都应该使用“volatile”修饰符声明,以防止线程级缓存该值

    如果你想强制进行顺序排序,你应该质疑为什么你首先要使用线程而不是顺序循环

  2. # 2 楼答案

    实际上有两个问题

    1)。Synchronization块特定于Thread1实例

    你应该使用其中一种

     synchronized(TestSync.class) {  
                    //  
                    //
                }
    

    或者

    synchronized(Thread1.class) {  
                    //  
                    //
                }
    

    2)。核心问题是。 Setting the static variableSystem.out.println()也应该同步,这样generationprinting的值将按顺序排列

  3. # 3 楼答案

    你想完成什么?您的代码只同步对特定TestSync实例的调用。因为每个线程都创建自己的实例,所以就好像根本没有同步任何东西一样。您的代码没有做任何事情来同步或协调不同线程之间的访问

    我建议以下代码可能更符合您的目标:

    public static void main (String[] args) throws java.lang.Exception {
            for (int i = 0; i < 10; i++) {  
                new Thread1().start();  
            }  
    }
    
    //no need for this to be an instance method, or internally synchronized
    public static int getNum(int i) {  
           return i + 1;  
    }
    
    static class Thread1 extends Thread {  
        static Integer value = 0;  
    
        @Override  
        public void run() {  
            while (value < 100) {
                synchronized(Thread1.class) {  //this ensures that all the threads use the same lock
                    value = getNum(value);  
                    System.out.println("Thread-" + this.getId() + ":  " + value);  
                }
    
                //for the sake of illustration, we sleep to ensure some other thread goes next
                try {Thread.sleep(100);} catch (Exception ignored) {} 
            }
        }  
    }
    

    这里有一个活生生的例子:http://ideone.com/BGUYY

    请注意getNum()基本上是多余的。如果你用一个简单的value++;替换value = getNum(value);,上面的例子也会起同样的作用