简体   繁体   English

Java:线程不起作用

[英]Java: Thread doesn't work

I'm trying to start a thread in a for-loop. 我正在尝试在for循环中启动线程。 This task should only wait for a second (Thread.sleep()), so every time the loop starts over again, a new thread is started and it should cause the code after the thread to wait until it is executed. 该任务仅需等待一秒钟(Thread.sleep()),因此,每次循环重新开始时,都会启动一个新线程,并且该线程应使该线程之后的代码等待执行。

public void count()
{
    for(int i = 29; i>=0; i--)
    {
        Thread t1;
        t1 = new Thread(new TimerClass());
        t1.start();
        String s = String.valueOf(i); 
        jLabel6.setText(s);
        System.out.println(s);
    }
}


public class TimerClass implements Runnable{

   @Override
   public void run()
   {
       try{
           Thread.sleep(1000);
           System.out.println("Timer");
       } catch(InterruptedException e)
       {
       }
   }
}

As you can see, I implemented in both methods System.out.println() to check if they are actually executed. 如您所见,我在两个方法System.out.println()中都实现了它们,以检查它们是否实际执行。 I get this: 我得到这个:

29
28
27
26
...//25 - 3
2
1
0
Timer
Timer
Timer
//in all 29 times Timer

So it should be 29, Timer, 28, Timer and so on, but it isn't. 因此应该是29,Timer,28,Timer等,但事实并非如此。 Does anyone know what's wrong with the code? 有人知道代码有什么问题吗? Thanks a lot. 非常感谢。

Your main loop that is starting the thread is likely dominating the CPU, so it finishes doing its entire loop and only then do the threads get a chance to go. 您正在启动线程的主循环可能会占据CPU的主导地位,因此它完成了整个循环,然后线程才有机会离开。

In fact, given that all of your threads sleep for an entire second and you're only looping 29 times, you're guaranteed that your loop will finish (and print all of the numbers) before your threads do. 实际上,考虑到所有线程都睡了一秒钟,而您只循环了29次,因此可以确保循环将在线程执行之前完成(并打印所有数字)。 Add a sleep to your main loop if you want the threads to print - remember, the main loop doesn't stop when you start a thread. 如果要打印线程,请在主循环中添加睡眠-请记住,启动线程时主循环不会停止。

You can join a thread to the main thread so first your thread will finished then main thread 您可以将一个线程加入主线程,这样您的线程将先完成,然后再进入主线程

public void count()
{
    for(int i = 29; i>=0; i--)
    {
        Thread t1;
        t1 = new Thread(new TimerClass());
        t1.start();
        t1.join();
        String s = String.valueOf(i); 
        jLabel6.setText(s);
        System.out.println(s);
    }
}

Here is my code for spawning 2 threads or one thread depends on arrayList size but in my case this threads are doing much more complex tasks then just waiting 1 sec 这是我产生2个线程或一个线程的代码,它取决于arrayList的大小,但是在我的情况下,该线程正在执行更复杂的任务,然后等待1秒钟

for (int i = 0; i < array.size(); i += 2) {
            Thread t1 = null;
            Thread t2 = null;

            if (i < array.size() - 1 && array.size() > 1) {

                t1 = new Thread(array.get(i));
                t2 = new Thread(array.get(i + 1));
                t1.start();
                t2.start();

            }

            else {

                t2 = new Thread(array.get(i));

                t2.start();
            }
            if (t1 != null)
                t1.join();
            if (t2 != null)
                t2.join();
              }

In my code I populate arrayList with Objects that Implements Runnable interface. 在我的代码中,用实现Runnable接口的对象填充arrayList。

Even if you sleep the thread for 1ms, your results would be the same. 即使您将线程休眠1毫秒,您的结果也将相同。 If you can manage the thread to sleep for the time less than it takes to print the results, your result could be as expected. 如果您可以管理线程休眠的时间少于打印结果所花费的时间,则结果可能与预期的一样。 Here is my code where I have put the time of 1 ms but yet the results are the same. 这是我的代码,我将时间设置为1 ms,但结果却是相同的。

public class MultiThreading implements Runnable
{
       public void run()
       {
           try
           {
               Thread.sleep(1);
               System.out.println("Timer");
           } 
           catch(Exception e)
           {

           }
       }

    public static void main(String [] args)
    {
        for(int i = 29; i>=0; i--)
        {
            Thread t1;
            t1 = new Thread(new MultiThreading());
            t1.start();
            String s = String.valueOf(i); 
            System.out.println(s);
        }
     }
}

If you comment out the Thread.sleep(1) method, then your results are as you expected. 如果您注释掉Thread.sleep(1)方法,则结果将与预期的一样。

延迟足以让count()中的for循环在可以从线程打印“计时器”之前完成。

What is happening is that the thread you started starts executing and immediately goes to sleep. 发生的事情是,您启动的线程开始执行并立即进入睡眠状态。 In the meantime, your loop just keeps running. 同时,您的循环不断运行。 As the whole point of threads is that they run asynchronously, I don't really understand why you think your main loop should be waiting for it to finish sleeping. 因为线程的全部要点是它们异步运行,所以我不太了解为什么您认为您的主循环应该等待它完成睡眠。 The thread has started running and is now running independently of the main loop. 该线程已开始运行,并且现在独立于主循环运行。

If you want to wait for the thread you just started to finish (in which case, you might as well use a method), then use one of the synchronisation primitives, ie Thread.wait() . 如果要等待刚开始完成的线程(在这种情况下,您也可以使用一种方法),请使用同步原语之一,即Thread.wait()

What you actually want to do is block your main thread while another thread is running. 您实际要做的是在另一个线程运行时阻塞您的主线程。 Please don't use Thread#sleep statements, as these are unreliable in order to "make your application work". 请不要使用Thread#sleep语句,因为它们不可靠,无法“使您的应用程序正常工作”。 What you want to use instead is Thread#join. 您要使用的是Thread#join。 See dharr his code for an example. 有关示例,请参见dharr的代码。

Also, it's better to use Executors and ExecutorServices when creating threads or running async tasks. 同样,在创建线程或运行异步任务时最好使用ExecutorsExecutorServices

Threads are interesting. 线程很有趣。 Think of a virtual thread as a physical thread. 将虚拟线程视为物理线程。 There are many threads on the clothes you're wearing, all working at the same time to hold your shirt together. 您穿的衣服上有很多线,所有线都同时工作以将衬衫固定在一起。 In virtual terms what Thread.start() does is start a thread on a different strand WHILE the following code continues to execute, (ie Two Threads work simultaneously like 2 runners run next to each other). 在虚拟方面有什么Thread.start()的作用是启动一个线程在不同的链,而下面的代码继续执行(即两个线程同时工作,像2名选手下次运行到对方)。 Consider putting a break point right after Thread.start() . 考虑在Thread.start()之后放置一个断点。 You'll understand. 你会明白的。

For your desired effect, just put a Thread.sleep() in the main loop. 为了达到理想的效果,只需将Thread.sleep()放入主循环即可。 This will cause an output of 这将导致输出

29
Timer
28
Timer
// etc.

Hope this helped. 希望这会有所帮助。

Jarod. Jarod。

Another analogy to the threads in a shirt: 另一个类似于衬衫中的线的类比:

Think of threads as coworkers to your main programm (which is a thread itself). 将线程视为主程序的协作者(线程本身)。 If you start a thread, you hand some work to this coworker. 如果启动线程,则将一些工作交给此同事。 This coworker goes back to his office to work on this task. 该同事回到他的办公室从事这项工作。 You also continue to do your task. 您还将继续执行任务。

This is why the numbers will appear before the first thread/coworker will output anythig. 这就是为什么数字将在第一个线程/同事输出anythig之前出现的原因。 You finished your task (handing out work to other coworkers) before he finished his. 在他完成任务之前,您已经完成了任务(将工作分发给其他同事)。

If you want to give out some work and then wait for it to be finished, use t1.join() as suggested by others. 如果要分发一些工作然后等待完成,请按照其他人的建议使用t1.join()。 But if you do this, it is senseless to create new Threads, because you don't (seem) to want to process something in parallel (with many coworkers) but in a specific order - you can just du it yourself. 但是,如果执行此操作,则创建新的线程是没有意义的,因为您(似乎)不想(与许多同事)以特定的顺序并行处理某些事情-您可以自己进行处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM