Java中线程的正确方法

时间:2015-09-21 12:39:34

标签: java multithreading

我开始学习Java中的线程,现在我有点困惑。 我希望这是一个正确的问题。 我制作了一个小程序进行测试:

public class GetInfo implements Runnable { 
    //private static boolean stopPointerInfo = false;   
    private static  Thread tn; 

    public static void StartPointerInfo() {
        //stopPointerInfo = false;
        tn = new Thread(new GetInfo());
        tn.start();
        System.out.println("After start1");
    }

    public static void StopPointerInfo() {
        //stopPointerInfo = true;
        tn.interrupt();
    }

    @Override
    public void run() {
        //  while (stopPointerInfo == false) {

        while (! tn.isInterrupted() ) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                tn.interrupt(); 
            }
            .
            .
            doSomething
        }
    }
}

因为run()方法必须知道哪个线程被中断,所以我必须使用线程tn的全局定义?

我应该像我一样使用interrupt()方法,还是应该像评论一样使用布尔变量?

使用此方法,我无法使用interrupt,我必须使用布尔版本,因为Runnable r不知道此处的线程吗?

public class GetInfo {
    private static boolean stopPointerInfo = false;

    public static void StartPointerInfo() {
        stopPointerInfo = false;
        getPointerInfo();
    }

    public static void StopPointerInfo() {
        stopPointerInfo = true;
    }

    public static void getPointerInfo() {
        Runnable r = new Runnable() { 

            @Override               
            public void run() {
            while (stopPointerInfo == false) {

                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) { }
                    .
                    .
                    doSomething
                }
            }   
        };
        new Thread(r).start();  
    }
}

2 个答案:

答案 0 :(得分:0)

布尔标志解决方案很脆弱,因为无法保证不同线程之间可以看到更新。要解决此问题,您可以将其声明为volatile,但如果设置布尔标志,则不要像第一个版本那样中断sleep调用。因此,首选使用中断。

我认为没有理由将Thread tn声明为静态。你可以使用:

public class GetInfo implements Runnable { 
    private final Thread tn; 

    private GetInfo() {
        this.tn = new Thread(this);
        this.tn.start();
    }

    public static GetInfo StartPointerInfo() {
        GetInfo info = new GetInfo();
        System.out.println("After start1");
        return info;
    }

    public void StopPointerInfo() {
        tn.interrupt();
    }
    ...
}

并像这样使用它:

GetInfo infoWorker = GetInfo.StartPointerInfo();
...
infoWorker.StopPointerInfo();

答案 1 :(得分:0)

您无需使用static Thread

run()方法中,您需要测试当前线程是否已被中断。您无需访问tn。你可以这样做:

    Thread.currentThread().isInterrupted();

    Thread.interrupted();

(注意这两者的行为是不同的。一个清除中断标志而另一个不清除。)

或者,您可以将static字段更改为实例字段,并创建所有GetInfo方法实例方法。这意味着您可以实例化GetInfo的多个实例,每个实例都创建自己的Thread并在实例字段中保存引用。

还有两点:

  • 您创建然后处理线程的方式效率很低。 (启动一个线程很昂贵。)更好的方法是重构代码,以便它可以使用thread pool

  • 调用您的方法StartPointerInfoStopPointerInfo是不好的。 Java方法名称应始终以小写字母开头。