1、简介。进程和线程:简单的说就是进程负责为程序开辟内存空间,线程负责具体的执行单元(执行路径)。
一个进程中可以有多个执行路径,称为多线程。CPU一次只能执行一个进程,但是一个进程内部可以有多个线程在执行。
最早的多进程,多线程效果其实是CPU进行快速切换的效果,由于切换速率很快用户不能发现。现在可以使用多CPU来实现。
参考:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html
2、线程状态图
3、线程的创建:进程和线程是由系统开启的,Java通过和底层进行交互,暴露出Runnable接口和Thread类来供用户创建线程。
线程创建的第一种方式和注意事项
第一种创建方式是继承Thread类,有两个问题:
1、如果这个类有自己的父类则会引起冲突(当然可以将其父类继承Thread类,但是不建议这样做)
2、如果只是想将该类中的方法作为线程的执行任务而不想作为一个线程对象(因为会包含许多线程相关的无用方法)
此时可以使用第二种方式:实现Runnable接口,具体过程见下:
!!!多线程还有问题就是
1、使用执行代码中的数据问题,就是这些数据是否是同一份(例如买票问题,开多个窗口即线程,但是卖的是同一批票)
2、在多个线程使用同一共享数据的安全问题
1 class SynLockDemo 2 { 3 public static void main(String[] args){ 4 Ticket t=new Ticket(); 5 Thread t1=new Thread(t); 6 Thread t2=new Thread(t); 7 t1.start(); 8 try{Thread.sleep(10);}catch (InterruptedException e){} 9 t.flag=false; 10 t2.start(); 11 } 12 } 13 class Ticket implements Runnable 14 { 15 private int num=100; 16 boolean flag=true; 17 //Object obj=new Object(); 18 public void run(){ 19 /* 20 关于同步应该注意到 21 1、同步是由synchronized修饰的,但是锁不是同步的特性,因为要在其后加一个对象作为锁使用 22 2、同步函数并没有声明一个锁却有同步效果,而函数天然具有一个对象this(除了static函数) 23 下面的操作是将同一段操作分别用同步代码块和同步函数封装,用一个标志选择进入两个不同的块中 24 如果两个线程使用的是同一个锁,则不会出现安全隐患(在这里就是0,-1,-2号票) 25 实践证明:使用this对象时正常,使用其他对象时有安全问题 26 27 由于static函数随着类加载而加载,所以没有this,但是当类加载进内存时会生成一个类文件对象, 28 !!!用this.getClass()/类名.class获取,两者的区别是:前者是非静态的方法,后者是用类静态获取 29 30 注意:同步函数可以看作是同步代码块在使用this时的特例 31 */ 32 if(flag){ 33 while(true){ 34 //synchronized(obj){ 35 synchronized(this){ 36 if(num>0){ 37 try{Thread.sleep(10);}catch (InterruptedException e){} 38 System.out.println(Thread.currentThread().getName()+"...obj..."+num--); 39 } 40 } 41 } 42 }else{ 43 while(true){ 44 show(); 45 } 46 } 47 } 48 public synchronized void show(){ 49 if(num>0){ 50 System.out.println(Thread.currentThread().getName()+"...this..."+num--); 51 } 52 } 53 }
1 class DeadLockDemo 2 { 3 public static void main(String[] args){ 4 Ticket t=new Ticket(); 5 Thread t1=new Thread(t); 6 Thread t2=new Thread(t); 7 t1.start(); 8 try{Thread.sleep(10);}catch (InterruptedException e){} 9 t.flag=false; 10 t2.start(); 11 } 12 } 13 class Ticket implements Runnable 14 { 15 private int num=100; 16 boolean flag=true; 17 Object obj=new Object(); 18 public void run(){ 19 /* 20 死锁发生在一段线程执行代码中有多个锁,且锁是嵌套存在的,这时多个线程持有了不同锁而且互不相让,这时就引发死锁问题 21 死锁的表现就是代码运行非正常终止。 22 */ 23 if(flag){ 24 while(true){ 25 synchronized(obj){ 26 show(); 27 } 28 } 29 }else{ 30 while(true){ 31 show(); 32 } 33 } 34 } 35 public synchronized void show(){ 36 synchronized(obj){ 37 if(num>0){ 38 System.out.println(Thread.currentThread().getName()+"...this..."+num--); 39 } 40 } 41 } 42 }