关于JAVA多线程切换与时间片分配的问题

时间:2022-01-15 02:05:37
package com.lwj;

public class ThreadTest {

public static void main(String[] args) {
MyThread th = new MyThread();
new Thread(th).start();
new Thread(th).start();
new Thread(th).start();
new Thread(th).start();
}
}

class MyThread implements Runnable {
int tickets = 20;

//Object obj = new Object();

public void run() {
while (true) {
synchronized (this) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
System.out.println("现在卖第" + tickets + "张 买卖票窗口:"
+ Thread.currentThread().getName());
tickets--;
} else {
System.out.println("窗口" + Thread.currentThread().getName()
+ "票已经卖完");
break;
}
}
}
}
}
有的卖的多有的卖的少。 
由此我产生了以下几个疑问: 
1,JAVA的线程是抢占式的,但又遵守支持时间片的操作系统的时间片调度,那么这里的抢占与时间片轮换之间又有怎样的关系,是怎么协调的? 
2,每个线程的时间片分配大小是否相等? 
3,以上程序中的线程为什么不是依次的执行,比如Thread-0执行后应该是Thread-1执行,但结果确实Thread-3在执行,当Thread-0睡眠过后,执行剩余的代码,外面等待的应该是Thread-2啊,那怎么会执行Thread-3呢? 
4,为什么每个线程的执行时间不是一样的长? 
期盼大家能帮下我--一个渴望学习JAVA的初学者

13 个解决方案

#1


该回复于2015-05-26 11:23:26被管理员删除

#2


1 JVM不保证线程一定会运行
2 也就不保证他们会被分配相同的处理时间

如果你想平均,就自己控制线程,比如用令牌标志。

#3


4,为什么每个线程的执行时间不是一样的长? 

  JVM

#4


时间片大小是操作系统设定的,调度时优先级高的获得时间片的概率大.(影响时间片大小设置的主要因素有:系统响应时间,就绪进程数目,计算机处理能力).
JAVA抢占式是根据线程优先级分配时间片,最底层还是由具体操作系统实现的.如果操作系统不将时间片分配给虚拟机,JAVA也就不能保证线程一定能执行了.
也就是说,要综合考虑虚拟机和OS对线程执行的影响.

#5


就那你这个卖票的来说。如果有一张票正在卖出,那么其他人就不能再对这张票做任何的处理,其他人可以做除了这张票以外的票其他漂,在做的过程中,电脑会根据时间片,分给你一个要处理的进程,,至于分配的时间间是多少,你要自己控制

#6


先格式化一下:

package com.lwj;

public class ThreadTest {

public static void main(String[] args) {
MyThread th = new MyThread();
new Thread(th).start();
new Thread(th).start();
new Thread(th).start();
new Thread(th).start();
}

}


class MyThread implements Runnable {

int tickets = 20;

public void run() {
while (true) {
synchronized (this) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("现在卖第" + tickets + "张 买卖票窗口:" + Thread.currentThread().getName());
tickets--;
} else {
System.out.println("窗口" + Thread.currentThread().getName() + "票已经卖完");
break;
}
}
}
}

}

#7


1. Java 中 JVM 的线程调度方式不一定是抢占式的(它要依赖操作系统的线程调度),要具体看 JVM 所在的操作系统,也有可能是协作试的。(Windows 确实是抢占式的)而给线程分配时间片是实现抢占式线程调度的一种手段。
2. 同 1 依赖于具体操作系统,优先级越高的线程获得的运行机会越多。
3. start 方法只是将线程切换到可运行状态,不代表启动后线程就马上开始运行,有可能当 main 线程执行结束后(此时4个线程都已启动)它才被线程调度程序撤下 CPU,此时因为4个线程优先级相同,所以它们竞争着去争夺运行机会,至于谁抢到要看线程调度器的调度。所以不会按顺序依次执行的。我试的几次 Thread-1 Thread-2 根本没抢到运行机会,Thread-3 Thread-4 运行结束后 1 2 才打印出“窗口Thread-1票已经卖完”“窗口Thread-2票已经卖完”。
4. 同 3。

#8


优先级越高的线程获得的运行机会越多

#9


线程执行是无法控制的,所以谁先后,执行多长都很难控制

可以通过使用锁来控制线程按顺序执行.

#10


引用 9 楼 gonxi 的回复:
线程执行是无法控制的,所以谁先后,执行多长都很难控制 

可以通过使用锁来控制线程按顺序执行.


楼主别被误导,同步锁不是用来控制线程执行顺序的,而是防止多个线程同时操作同一个对象而破坏对象内部状态的一种保护机制。线程间协作以达到按一定顺序执行可以用 Thread 的  join() 方法。

#11


终于看到了有个正确的解答了。

#12


引用 10 楼 sagezk 的回复:
引用 9 楼 gonxi 的回复:
线程执行是无法控制的,所以谁先后,执行多长都很难控制

可以通过使用锁来控制线程按顺序执行.


楼主别被误导,同步锁不是用来控制线程执行顺序的,而是防止多个线程同时操作同一个对象而破坏对象内部状态的一种保护机制。线程间协作以达到按一定顺序执行可以用 Thread 的join()方法。

说的好

#13


兰州烧饼

#1


该回复于2015-05-26 11:23:26被管理员删除

#2


1 JVM不保证线程一定会运行
2 也就不保证他们会被分配相同的处理时间

如果你想平均,就自己控制线程,比如用令牌标志。

#3


4,为什么每个线程的执行时间不是一样的长? 

  JVM

#4


时间片大小是操作系统设定的,调度时优先级高的获得时间片的概率大.(影响时间片大小设置的主要因素有:系统响应时间,就绪进程数目,计算机处理能力).
JAVA抢占式是根据线程优先级分配时间片,最底层还是由具体操作系统实现的.如果操作系统不将时间片分配给虚拟机,JAVA也就不能保证线程一定能执行了.
也就是说,要综合考虑虚拟机和OS对线程执行的影响.

#5


就那你这个卖票的来说。如果有一张票正在卖出,那么其他人就不能再对这张票做任何的处理,其他人可以做除了这张票以外的票其他漂,在做的过程中,电脑会根据时间片,分给你一个要处理的进程,,至于分配的时间间是多少,你要自己控制

#6


先格式化一下:

package com.lwj;

public class ThreadTest {

public static void main(String[] args) {
MyThread th = new MyThread();
new Thread(th).start();
new Thread(th).start();
new Thread(th).start();
new Thread(th).start();
}

}


class MyThread implements Runnable {

int tickets = 20;

public void run() {
while (true) {
synchronized (this) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("现在卖第" + tickets + "张 买卖票窗口:" + Thread.currentThread().getName());
tickets--;
} else {
System.out.println("窗口" + Thread.currentThread().getName() + "票已经卖完");
break;
}
}
}
}

}

#7


1. Java 中 JVM 的线程调度方式不一定是抢占式的(它要依赖操作系统的线程调度),要具体看 JVM 所在的操作系统,也有可能是协作试的。(Windows 确实是抢占式的)而给线程分配时间片是实现抢占式线程调度的一种手段。
2. 同 1 依赖于具体操作系统,优先级越高的线程获得的运行机会越多。
3. start 方法只是将线程切换到可运行状态,不代表启动后线程就马上开始运行,有可能当 main 线程执行结束后(此时4个线程都已启动)它才被线程调度程序撤下 CPU,此时因为4个线程优先级相同,所以它们竞争着去争夺运行机会,至于谁抢到要看线程调度器的调度。所以不会按顺序依次执行的。我试的几次 Thread-1 Thread-2 根本没抢到运行机会,Thread-3 Thread-4 运行结束后 1 2 才打印出“窗口Thread-1票已经卖完”“窗口Thread-2票已经卖完”。
4. 同 3。

#8


优先级越高的线程获得的运行机会越多

#9


线程执行是无法控制的,所以谁先后,执行多长都很难控制

可以通过使用锁来控制线程按顺序执行.

#10


引用 9 楼 gonxi 的回复:
线程执行是无法控制的,所以谁先后,执行多长都很难控制 

可以通过使用锁来控制线程按顺序执行.


楼主别被误导,同步锁不是用来控制线程执行顺序的,而是防止多个线程同时操作同一个对象而破坏对象内部状态的一种保护机制。线程间协作以达到按一定顺序执行可以用 Thread 的  join() 方法。

#11


终于看到了有个正确的解答了。

#12


引用 10 楼 sagezk 的回复:
引用 9 楼 gonxi 的回复:
线程执行是无法控制的,所以谁先后,执行多长都很难控制

可以通过使用锁来控制线程按顺序执行.


楼主别被误导,同步锁不是用来控制线程执行顺序的,而是防止多个线程同时操作同一个对象而破坏对象内部状态的一种保护机制。线程间协作以达到按一定顺序执行可以用 Thread 的join()方法。

说的好

#13


兰州烧饼