Java线程问题(基础回顾)
1、概念:线程是运行程序(进程)中单个顺序的小程序,一个进程可以由多个线程组成,而这多个线程共享同一个存储空间,这使得线程间的通信比较容易。在一个多进程的程序中,如果要切换到另一个进程,需要改变地址空间的位置。然而在多线程的程序中,就不会出现这种情况,因为它们位于同一个内存空间内,只需改变运行的顺序即可。
2、什么是多线程:多线程指单个程序可通过同时运行多个不同线程,以执行不同任务。所谓同时,也要依据CPU。如果是多个CPU,则并发运行,如是一个CPU,则根据系统具体情况,执行多个线程。
3、创建线程的方法一般有两种:
一种是通过实现Runnable接口的方式创建线程。
一种是通过从Thread类中去继承来创建线程。
4、线程的优先级:
【Demo】
1 computer t = new compute(); 2 3 computer1 t = new compute1(); 4 5 //setPriority是一个从1~10之间的正整数,数值越大,优先级别越高 6 7 //系统默认的优先级是5 8 9 t.setPriority(10); 10 11 t.start(); 12 13 t1.start();
5、线程的休眠与唤醒:
//休眠
1 sleep(毫秒数);
//唤醒
【Demo】
1 compute t = new computer(); 2 3 t.start(); 4 5 t.interrupt();
1 class compute extends Thread{ 2 3 int i=0; 4 5 public void run() 6 7 { 8 9 System.out.println("在工作中,不要打扰"); 10 11 try 12 13 { 14 15 sleep(1000000); 16 17 } 18 19 catch(Exception e) 20 21 {System.out.println("哦,电话来了"); 22 23 } 24 25 } 26 27 }
因为使用了唤醒语句后,在输出“在工作中,不要打扰”后休眠。然后又立即会被唤醒输出“哦,电话来了”。
6、线程让步:
所谓线程让步,就是使当前正在运行的线程对象退出运行状态,让其他线程运行,其方法是通过调用yield()来实现。这个方法不能将运行权让给指定的线程,只是允许这个线程把运行权让出来,至于给谁,这就是抢占功能的事情了。
【Demo】
1 public class thread1{ 2 3 public static void main(String[] args){ 4 5 compute t = new compute(); 6 7 compute t1 = enw compute1(); 8 9 t.start(); 10 11 t1.start(); 12 13 } 14 15 } 16 17 class compute extends Thread{ 18 19 int i=0; 20 21 public void run(){ 22 23 for(int i=0;i<10;i++){ 24 25 System.out.println(i); 26 27 yield(); 28 29 } 30 31 } 32 33 } 34 35 class compute1 extends Thread{ 36 37 public void run(){ 38 39 for(int i=0;i<10;i++){ 40 41 System.out.println("这个数字是:"+i); 42 43 } 44 45 } 46 47 }
运行结果:
0
这个数字是:0
这个数字是:1
这个数字是:2
这个数字是:3
这个数字是:4
这个数字是:5
这个数字是:6
这个数字是:7
1
这个数字是:8
这个数字是:9
2
3
4
5
6
7
8
9
从运行结果来看,第一个线程比第二个线程运行的几率要小,因为它总是放弃运行权。
7、线程同步:
【Demo】
1 public class thread11{ 2 3 public static void main(String[] args){ 4 5 compute t = new compute(); 6 7 new Thread(t).start(); 8 9 new Thread(t).start(); 10 11 new Thread(t).start(); 12 13 } 14 15 } 16 17 class compute extends Thread{ 18 19 int i=10; 20 21 static Object obj= new Object(); 22 23 public void print(){ 24 25 System.out.println(Thread.currentThread().getName()+":" +1); 26 27 i--; 28 29 } 30 31 public void run(){ 32 33 while(i>0){ 34 35 synchronized(obj){ 36 print(); 37 38 } 39 40 try 41 42 { 43 44 sleep(1000); 45 46 } 47 48 catch(Exception e){} 49 50 } 51 52 } 53 54 }
运行结果
Thread-1:10
Thread-2:9
Thread-3:8
Thread-1:7
Thread-2:6
Thread-3:5
Thread-1:4
Thread-2:3
Thread-3:2
Thread-1:1
这里用到的是同步块的概念
synchronized(someobject) { 代码块 }
也可以写成同步化方法的方式
1 synchronized void f() 2 { 3 代码块 4 }
【Demo】
1 synchronized void print(){ 2 3 System.out.println(Thread.cui--); 4 5 }
答疑-线程和线程之间怎么通信?
答:共享一个变量,并对此变量的访问进行同步,因为它们共享一个内存空间,所以相比之下,它比进程之间通信要简单容易的多。
答疑-什么是线程的饥饿?
答:饥饿是由于别的并发进程的激活,而导致持久占有所需资源。饥饿是一个异步过程,预测的时间内不能被激活,最常遇到的线程的两个缺陷是死锁和饥饿。
答疑-什么是线程的死锁?
答:当一个或多个进程,在一个给定的任务中,协同作用、互相干涉,而导致一个或者更多进程永远等待下去,死锁就发生了。
与此类似,当一个进程永久性地占有资源,使得其他进程得不到该资源,就发生了饥饿。