Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/194.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 停止线程未使用函数setRunning(false)_Java_Android_Multithreading_Canvas - Fatal编程技术网

Java 停止线程未使用函数setRunning(false)

Java 停止线程未使用函数setRunning(false),java,android,multithreading,canvas,Java,Android,Multithreading,Canvas,我有一个项目,用画布画一条线。我的项目(下载)将创建一个随机数,并使用画布在线连接它们。它工作得很好。但问题是,当我的应用程序运行时,我单击HOME按钮,然后我的应用程序将崩溃,如 FATAL EXCEPTION: Thread-10001 java.lang.NullPointerException at com.example.waveplot.WaveformView.PlotPoints(WaveformView.java:78) at com.example.waveplot.Wave

我有一个项目,用画布画一条线。我的项目(下载)将创建一个随机数,并使用画布在线连接它们。它工作得很好。但问题是,当我的应用程序运行时,我单击HOME按钮,然后我的应用程序将崩溃,如

FATAL EXCEPTION: Thread-10001
java.lang.NullPointerException
at com.example.waveplot.WaveformView.PlotPoints(WaveformView.java:78)
at com.example.waveplot.WaveformPlotThread.run(WaveformPlotThread.java:35)
如何修复它?非常感谢你。 让我解释一下我的申请。我的申请包括三类:

WaveformView.java: class to draw the line in thread with random number.
MainActivity.java: main calss and create the random number and call WaveformView class
WaveformPlotThread: create a thread and manager canvas
这是我的密码 MainActivity.java

        private Runnable Timer_Tick = new Runnable() {
        public void run() {
            numRandom=genNum(0,200)-100;// from -100 to 100
            if(dataIndex1<MAX_SAMPLES) 
                dataY[dataIndex1++] = numRandom;
            else
            {
                dataY[MAX_SAMPLES-1] = numRandom;
               for (int i = 0; i <  WIDTH/10 - 1; i++)
                   //Shift data
                   dataY[i]=dataY[i+1];

            }
            mWaveform.set_data(dataY);
        }
     };
这是一个日志文件

 D/D(9747): STOOOOOOOOOOOOOOOOOOP
 W/SurfaceView(9747): CHECK surface infomation creating=false formatChanged=false sizeChanged=false visible=false visibleChanged=true surfaceChanged=true realSizeChanged=false redrawNeeded=false left=false top=false
 W/System.err(9747): java.lang.IllegalThreadStateException: Thread already started.
 W/System.err(9747):    at java.lang.Thread.start(Thread.java:1045)
 W/System.err(9747):    at com.example.waveplot.WaveformView.surfaceCreated(WaveformView.java:41)
 W/System.err(9747):    at android.view.SurfaceView.updateWindow(SurfaceView.java:609)
 W/System.err(9747):    at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:235)
 W/System.err(9747):    at android.view.View.dispatchWindowVisibilityChanged(View.java:7625)
 W/System.err(9747):    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1047)
 W/System.err(9747):    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1047)
 W/System.err(9747):    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1047)
 W/System.err(9747):    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1047)
 W/System.err(9747):    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1047)
 W/System.err(9747):    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1047)
 W/System.err(9747):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1346)
 W/System.err(9747):    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1121)
 W/System.err(9747):    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4598)
 W/System.err(9747):    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
 W/System.err(9747):    at android.view.Choreographer.doCallbacks(Choreographer.java:555)
 W/System.err(9747):    at android.view.Choreographer.doFrame(Choreographer.java:525)
 W/System.err(9747):    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
 W/System.err(9747):    at android.os.Handler.handleCallback(Handler.java:615)
 W/System.err(9747):    at android.os.Handler.dispatchMessage(Handler.java:92)
 W/System.err(9747):    at android.os.Looper.loop(Looper.java:137)
 W/System.err(9747):    at android.app.ActivityThread.main(ActivityThread.java:4950)
 W/System.err(9747):    at java.lang.reflect.Method.invokeNative(Native Method)
 W/System.err(9747):    at java.lang.reflect.Method.invoke(Method.java:511)
 W/System.err(9747):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:997)
 W/System.err(9747):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:764)
 W/System.err(9747):    at dalvik.system.NativeStart.main(Native Method)
解决方案:根据Veritas的建议,我将创建新线程的函数放入到SurfaceCreated中

@Override
public void surfaceCreated(SurfaceHolder holder){
    plot_thread = new WaveformPlotThread(getHolder(), this);
    plot_thread.setRunning(true);
    plot_thread.start();

}   
public WaveformView(Context context, AttributeSet attrs){
    super(context, attrs);

    getHolder().addCallback(this);
    //plot_thread = new WaveformPlotThread(getHolder(), this);      
    dataY_color.setColor(Color.GREEN);
    dataY_color.setStrokeWidth(3);

}

使
\u运行
不稳定,因此读写是原子的。看

四件事

  • 检查PlotPoints方法中的canvas是否为null

    如果(画布==null){ return;//静默返回 }

    可能在surface上销毁的surfaceholder将返回一个空画布

  • 正如isalgueiro所建议的那样,让你以不稳定的方式运行/

  • 将_run的默认值设置为true,因为如果在某个地方启动此线程而没有将_run设置为true,则很可能在您可以对其执行任何有建设性的操作之前线程就结束了。默认值false在您的情况下没有任何意义

  • 不要扩展线程,而是实现runnable

  • 最后两点是更多的最佳实践

    --编辑-- 暂时在surfaceCreated中创建一个新线程,然后启动它,因为当_run设置为false时退出while循环的逻辑将使线程完成其运行方法,线程将死亡。该错误自指示线程一旦启动就无法启动。要么通过更正_run=false/true的逻辑重用线程,要么通过使用Executor ThreadPool采用更好的解决方案请参见。
    目前,您可以使用surfacecreated方法而不是构造函数来创建新线程。我遇到了相同的问题。我不明白为什么调用
    setRunning(false)
    线程不会停止,但我通过在另一个
    if(canvas!=null)
    语句中包装
    plot\u area.PlotPoints()
    绕过了
    NullPointerException
    。因此
    waveormplotthread
    中的
    run()
    方法如下所示:

    @Override
    public void run(){
        Canvas c;
        while(_run){
        //while(Thread.currentThread() == runner){
            c = null;
            try{
                c = holder.lockCanvas(null);
                synchronized (holder) {
                    if(c!=null) {
                        plot_area.PlotPoints(c);
                    }
                }
            }finally{
                if(c!=null){
                    holder.unlockCanvasAndPost(c);
                }
            }
        }
    }
    

    另外,作为旁注,
    @Override public void onDraw(Canvas Canvas)
    不是必需的,并且不建议重写
    onDraw()
    draw()
    。整个方法可以删除。

    如何在我的应用程序中使用它?它不起作用。请下载我的项目,并尝试使用您的编辑运行它。请注意,当应用程序运行时,按home(主页)按钮返回第一个点时,它将崩溃。然而,在运行应用程序时单击Home按钮仍然会出错。让我们再次检查我的项目。如果您提供了异常StackTracecan,您可以指出WaveformView.java中哪一行号是78,您能帮我展示一个在我的代码中使用它的示例吗?我正在读它。提前感谢我阅读了你的链接,但我不知道如何解决我的问题。你有什么办法解决我的问题吗?相关:谢谢你的评论。正如你所说,我更新了我的代码。然而,我的问题是,当应用程序。运行20秒后,画布将不会绘制。我不知道在我的代码中发生了什么。请在这里查看更多详细信息。请注意,这只发生在真实设备中。在模拟中,它没有problem@user8264我在Nexus7API 5.1.1、模拟Nexus5API 5.1.0和模拟LG OptimusAPI 4.1.1上运行了您的代码。他们都跑得很好。除了Optimus,它没有正确缩放
    SurfaceView
    ,但它仍然正确地绘制了绘图。不幸的是,我没有任何其他设备(除了更多的模拟器)可以测试。它可能特定于您的设备。请下载我的代码并在1分钟后运行。你可以看到问题所在。我记录了错误并发布了日志。目前,我通过删除plot_thread.setRunning(false)解决了这个问题;和plot_thread.setRunning(true);在set_数据中function@user8264我又运行了大约十分钟,没有问题。当logcat发生错误时,它是否有任何错误?实际上,我在logcat中找不到任何错误。它只是没有进入绘图区域。绘图点(c);在WaveformPlotThread中。我打印了_run标志,但它仍然是真实值。但是,我刚刚删除了两行plot_thread.setRunning(false);和plot_thread.setRunning(true);那么它工作得很好。我不知道如何检测错误。我在三星Galaxy S2和Note 2中运行它
    @Override
    public void surfaceCreated(SurfaceHolder holder){
        plot_thread = new WaveformPlotThread(getHolder(), this);
        plot_thread.setRunning(true);
        plot_thread.start();
    
    }   
    public WaveformView(Context context, AttributeSet attrs){
        super(context, attrs);
    
        getHolder().addCallback(this);
        //plot_thread = new WaveformPlotThread(getHolder(), this);      
        dataY_color.setColor(Color.GREEN);
        dataY_color.setStrokeWidth(3);
    
    }
    
    public class WaveformPlotThread extends Thread {
        private SurfaceHolder holder;
        private WaveformView plot_area;
        private volatile boolean _run = false;
    
    @Override
    public void run(){
        Canvas c;
        while(_run){
        //while(Thread.currentThread() == runner){
            c = null;
            try{
                c = holder.lockCanvas(null);
                synchronized (holder) {
                    if(c!=null) {
                        plot_area.PlotPoints(c);
                    }
                }
            }finally{
                if(c!=null){
                    holder.unlockCanvasAndPost(c);
                }
            }
        }
    }