方法产量如何运作?

发布于 2024-10-19 21:51:01 字数 271 浏览 4 评论 0原文

在javadoc中有说yield方法

使当前正在执行的线程对象暂时暂停并允许其他线程执行。

凯瑟琳·塞拉 (Katherine Sierra) 和伯特·贝茨 (Bert Bates) SCJP 书中说

yield() 应该做的是 使当前正在运行的线程头回到可运行状态,以允许其他线程 轮到他们时具有相同的优先级。

那么方法实际上在做什么呢?

In javadoc there is said that yield method

Causes the currently executing thread object to temporarily pause and allow other threads to execute.

And Katherine Sierra and Bert Bates SCJP book says that

yield() is supposed to do is
make the currently running thread head back to runnable to allow other threads of
the same priority to get their turn.

So what actually method is doing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

舟遥客 2024-10-26 21:51:01

对于多线程应用程序,yield 将导致当前正在执行的线程暂停执行并设置为等待状态。然后,JVM 将开始运行之前处于等待状态的另一个线程。

我相信刚刚产生的同一个线程在技术上可以安排重新启动。

不过我还没有在野外看到过这种情况。所以我认为避免是安全的。

详细说明:

在多线程环境中,线程按照 JVM 的意愿进行调度和不调度。因此,即使在代码中没有调用yield,当 JVM 决定应该这样做时,您的线程也可以/将会自动让位于其他线程。这使得多线程可以在只有一个处理核心的环境中工作。

调用yield只是告诉JVM将当前线程置于等待状态,即使JVM不打算这样做。

我将尝试举例说明:
下面是 2 个线程随着时间的推移执行的非常简化的说明(假设 1 个核心)-

Thread\Time    1    2    3    4    5    6    7    8    9
Thread 1    -----------       -----          -------
Thread 2               -------     ----------       ------

每当您看到 '-' 时,就表示有一个线程正在执行。 ' ' 表示线程正在等待。正如您所看到的,实际上一次只能运行 1 个线程。因此,当 1 运行时,另一个等待。 Yield 的目的是让其他线程有机会先于当前正在运行的线程运行。

Given a multi-threaded application, yield will cause the currently executing thread to pause execution and be set in a waiting state. The JVM will then begin running another thread that was previously in a waiting state.

I believe the same thread that just yielded could technically be scheduled to start again.

And I have yet to see this in the wild though. So I think it is safe to avoid.

To elaborate:

In a multi-threaded environment threads are scheduled and unscheduled off and on at the JVM's will. So, even if yield is not called in code, your thread can/will automatically yield to other threads when the JVM decides it should. This allows multi-threading to work in an environment with only one processing core.

Calling yield simply tells the JVM to put the current thread in a waiting state even if the JVM wasn't going to.

I shall attempt an illustration:
The following is a very simplified illustration of the execution of 2 threads over time (assume 1 core)-

Thread\Time    1    2    3    4    5    6    7    8    9
Thread 1    -----------       -----          -------
Thread 2               -------     ----------       ------

Whenever you see a '-' that means a thread is executing. A ' ' means that the thread is waiting. As you can see, only 1 thread can actually run at a time. So, while 1 runs, the other waits. What yield is intended to do is give other threads a chance to run ahead of the currently running thread.

贵在坚持 2024-10-26 21:51:01

yield() 通常用于当您在线程上等待某件事发生但又不想使用 while(condition){ ...}< 之类的内容阻塞 CPC 周期时/代码> . Yield() 的工作方式因平台而异,并且取决于线程调度程序,您不应依赖它以特定方式运行。

yield() is generally used when you are waiting on a thread for something to occur but don't want to block the CPC cycles with something like while(condition){ ...} . The way yield() works differ from platform to platform and depends on the Thread Scheduler and you shouldn't rely on it behaving in a particular way.

带刺的爱情 2024-10-26 21:51:01

它起源于协作多任务时代。
基本思想是,处理器仅执行一个线程,直到:

  1. 该线程结束
  2. 该线程执行一些阻塞操作,例如 object.wait()Thread.sleep,等待一些IO操作完成,等待一些对象监视器,或者类似的。
  3. 该线程调用 Thread.yield()。

在每种情况下,线程调度程序都会选择另一个线程来执行。因此,为了对其他线程公平,您可以在没有任何阻塞操作的较长循环中定期调用yield()。 (如果没有其他线程准备好运行,那么同一个线程将被再次调度,因此不会有太大的性能损失。)

在现代虚拟机中,线程切换可以在任何点发生,不仅是列出的这些,线程甚至可以同时执行,所以它并不是真正必要的,有些虚拟机可能会完全忽略它(类似于System.gc()。)

It originates from the time of cooperative multitasking.
The basic idea is, the processor executes only one thread until:

  1. this thread ends
  2. this thread does some blocking operation, like object.wait() or Thread.sleep, waiting on some IO operation to complete, waiting for some object monitor, or similar.
  3. this thread invokes Thread.yield().

In each of this cases the thread scheduler then selects another thread to execute. So, to be fair to other threads, you would in longer loops without any blocking operations regularly call yield(). (If no other thread is ready to run, then the same thread would be scheduled again, so no really big performance loss.)

In modern VMs thread switching can occur on any point, not only these listed, threads may even be executed simultaneously, so it is not really necessary, and some VMs may ignore it altogether (similar to System.gc().)

少女的英雄梦 2024-10-26 21:51:01

yield() 方法是为了确保应用程序中所有相同优先级的线程不会导致饥饿 。例如,一个应用程序中有五个线程,并且所有线程都具有相同的优先级。现在假设一个线程有机会运行,但该线程需要很长时间才能完成其任务,因此其他线程将没有机会运行。因此,为了避免这种情况,yield() 可以用来拯救。

yield() method is there to make sure that all same priority threads in a application would not cause starvation. For e.g. five threads are there in a application and all of them are of same priority. Now suppose one thread got chance to run and this thread is taking so long to complete its task and hence other threads wont get chance to run. So to avoid this kind of situations yield() is there to rescue.

黯然 2024-10-26 21:51:01

最终,对 yield() 的调用会导致调用像这样的操作系统方法,原则上这会将任务本身放回运行队列并让下一个任务运行(来源):

 /**
  * sys_sched_yield - yield the current processor to other threads.
  *
  * This function yields the current CPU to other tasks. If there are no
  * other threads running on this CPU then this function will return.
  */
 SYSCALL_DEFINE0(sched_yield)
 {
        /*
         *  lock this runqueue and disable interrupts.
         */
         struct rq *rq = this_rq_lock();

         schedstat_inc(rq, yld_count);
         current->sched_class->yield_task(rq);

         /*
          * Since we are going to call schedule() anyway, there's
          * no need to preempt or enable interrupts:
          */
         __release(rq->lock);
         spin_release(&rq->lock.dep_map, 1, _THIS_IP_);
         _raw_spin_unlock(&rq->lock);
         preempt_enable_no_resched();

         schedule();

         return 0;
 }

Ultimately, the call to yield() results in calling os methods like this, which in principle would put the task itself back in to the run queue and let the next task run (source):

 /**
  * sys_sched_yield - yield the current processor to other threads.
  *
  * This function yields the current CPU to other tasks. If there are no
  * other threads running on this CPU then this function will return.
  */
 SYSCALL_DEFINE0(sched_yield)
 {
        /*
         *  lock this runqueue and disable interrupts.
         */
         struct rq *rq = this_rq_lock();

         schedstat_inc(rq, yld_count);
         current->sched_class->yield_task(rq);

         /*
          * Since we are going to call schedule() anyway, there's
          * no need to preempt or enable interrupts:
          */
         __release(rq->lock);
         spin_release(&rq->lock.dep_map, 1, _THIS_IP_);
         _raw_spin_unlock(&rq->lock);
         preempt_enable_no_resched();

         schedule();

         return 0;
 }
心舞飞扬 2024-10-26 21:51:01

线程可能处于就绪(可运行)、阻塞(例如,等待某些 io 完成)或运行状态;这对于所有线程实现来说都是常见的,尽管某些特定的实现可能有更多的状态。

Yield 导致线程从运行状态变为可运行状态,并等待调度程序在将来再次将其更改为运行状态。这就是 SCJP 书中的意思。

对于线程来说,它似乎已经暂停了一段时间,就像 javadoc 中所描述的那样。所以这两种说法都是正确的,只是措辞不同。

Threads may be in states ready (runnable), blocked (e.g., waiting for some io to finish), or running; this is common to all thread implementations, although some particular implementations may have more states.

Yield causes the thread to change from running to runnable, and wait for the scheduler to change it to running again, in the future. This is what is meant in the SCJP book.

To the thread, it seems like it has been paused for a while, like described in the javadoc. So both statements are correct, just differently phrased.

悲念泪 2024-10-26 21:51:01

希望有帮助!

package yield;

public class ThreadYieldApp {

    Thread th1 = new Thread("Thread 1") {
        public void run() {

            for(int i = 0; i <= 10; i++) {
                System.out.println("Before Yield - " + Thread.currentThread().getName() + " at index - " + i);
                //Currently pauses the thread and checks for other threads of same priority, and passes control to it based on Thread Scheduler pick 
                Thread.yield();
                System.out.println("Currently running - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };

    Thread th2 = new Thread("Thread 2") {
        public void run() {
            for(int i = 0; i <= 10; i++) {
                System.out.println("Currently running - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };


    public static void main(String[] args) {
        ThreadYieldApp threadYieldApp = new ThreadYieldApp();
        threadYieldApp.th1.start();
        threadYieldApp.th2.start();
    }

    //Happy coding -- Parthasarathy S
}

Hope it helps!

package yield;

public class ThreadYieldApp {

    Thread th1 = new Thread("Thread 1") {
        public void run() {

            for(int i = 0; i <= 10; i++) {
                System.out.println("Before Yield - " + Thread.currentThread().getName() + " at index - " + i);
                //Currently pauses the thread and checks for other threads of same priority, and passes control to it based on Thread Scheduler pick 
                Thread.yield();
                System.out.println("Currently running - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };

    Thread th2 = new Thread("Thread 2") {
        public void run() {
            for(int i = 0; i <= 10; i++) {
                System.out.println("Currently running - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };


    public static void main(String[] args) {
        ThreadYieldApp threadYieldApp = new ThreadYieldApp();
        threadYieldApp.th1.start();
        threadYieldApp.th2.start();
    }

    //Happy coding -- Parthasarathy S
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文