1.一个单CPU的机器,如何同时执行多个线程?请简述其原理。
单CPU的计算机中,CPU同时只能执行一条指令,因此,在仅有一个CPU的计算机上不可能同时执行多个任务。而操作系统为了能提高程序的运行效率,将CPU的执行时间分成多个时间片,分配给不同的线程,当一个时间片执行完毕后,该线程就可能让出CPU使用权限交付给下一个时间片的其他线程执行。当然有可能相邻的时间片分配给同一线程。之所以表面上看是多个线程同时执行,是因为不同线程之间切换的时间非常短,也许仅仅是几毫秒,对普通人来说是难以感知的,这样就看似多个线程在同时执行了。
2.线程实例调用start()方法和调用run()方法有着天壤之别,前者是调用实例方法,只有主线程执行,只有一条执行路径,后者是启动线程。
3.任何线程一般都具有5种状态,即创建、就绪、运行、阻塞、终止状态。
1. 创建状态
在程序中用构造方法创建了一个线程对象后,新的线程对象就处于创建状态,此时,它已经获取了相应的资源,但还没有处于可运行状态,这时可以通过Thread类的方法来设置线程对象的属性,如设置线程名(setName())、设置线程优先级(setPriority())等。
2. 就绪状态
线程创建之后,就可以通过调用start()方法启动线程,即进入就绪状态。此时,线程将进入线程队列排队,等待CPU资源,这表明它已经具备了运行条件,在未获得CPU资源时,仍不能真正执行。举例来说,去医院看病,某主任的专家号每天只有20个,挂上号的病人还需在分诊处等待叫号。这里每个挂到专家号的病人可以看成一个就绪状态的线程。
3. 运行状态
当就绪状态的线程获得CPU资源时,即可转入运行状态,执行的run()方法。对于只有一个CPU的机器而言,任何时刻只能有一个处于运行状态的线程占用CPU,即获得CPU资源。延续上面医院看病的例子,被叫到的病人才能真正就诊,而每个主任专家在一个时刻只能为一个病人看病。
4
package com.bdqn3;
public class MyThread extends Thread {
public void run(){
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
package com.bdqn3;
public class Test1 {
public static void main(String[] args) {
MyThread m =new MyThread();
m.start();
}
}
package com.bdqn3;
public class MyThread2 implements Runnable {
public void run(){
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
package com.bdqn3;
public class Test2 {
public static void main(String[] args) {
Thread m=new Thread( new MyThread2() );
m.start();
}
}
package com.bdqn4;
public class Account {
private int balance=500;//余额
public int getbalance(){
return balance;
}
//取款
public void withdiaw(int amont){
balance =balance-amont;
}
}
package com.bdqn4;
public class TestAccount implements Runnable {
private Account acct=new Account();
public void run() {
for (int i = 0; i < 5; i++) {
makewithdrawal(100);
if(acct.getbalance()<0){
System.out.println("账户没钱了!");
}
}
}
private synchronized void makewithdrawal(int amt){
if(acct.getbalance()>=amt){
System.out.println(Thread.currentThread().getName()+"准备取款");
try {
Thread.sleep(500);//0.5s后取款
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//余额足够时
acct.withdiaw(amt);
System.out.println(Thread.currentThread().getName()+"完成取款!");
}else{
System.out.println("余额不足以支付"+Thread.currentThread().getName()+"余额为:"+acct.getbalance());
}
}
}
package com.bdqn4;
public class Test {
public static void main(String[] args) {
TestAccount ts=new TestAccount();
Thread one=new Thread(ts);
Thread two=new Thread(ts);
one.setName("张三");
two.setName("张三的妻子");
one.start();
two.start();
}
}