什么是线程
>>线程是每一个进程执行的顺序,该顺序是一个执行路径,或者叫做一个控制单元。 简单来说线程就是一个控制单元或者叫做一个执行路径。 >>是程序执行流的最小单位_____________________________________________________________________________________________________________________________________________________________什么是进程
>>进程是一个正在执行的程序。 >>进程是资源分配的基本单位。__________________________________________________________________________________________________________________________________________________________________
进程和线程的关系
每个进程至少有一个线程(线程是进程的一个实体,是被系统独立调度和分派的基本单位)______________________________________________________________________________________________________________________________________________________________________什么是多线程
在当个程序中运行多个线程完成不同的工作。 多线程具有随机性___________________________________________________________________________________________________________________________________________________________________生活中的例子
比如说,政府的行政楼,里面有很多办事窗口,每一个办事窗口相当于一个线程,行政楼相当于进程 多线程就是相当于行政楼多个窗口____________________________________________________________________________________________________________________________________________________________________在代码中定义一个执行线程的步骤
方法(一) >>继承Thread类 >>重新run()方法 >>调用start()方法 >>启动线程 >>调用run()方法在主函数中调用run方法和调用start方法的区别 >>直接调用run方法,相当于对象调用方法,这样我们创建了线程,并没有实际上运行了线程,产生的效果就是线执行run,然后在执行主函数(意思就是只有主函数这个线程在执行,我们定义的线程并没有执行)___________________________________________________________________________________________________________________________________________________________________________________________________方法(二)
>>声明实现Runnable接口的类(implements Runnable) >> 实现Runnable接口的run方法, >>然后可以分配该类的实例 创建实例对象 比如说买票系统里的Tick t=new Tick() >>在创建thread时作为一个参数来传递并启动。 因为这里的run方法指的是Runnable里的run方法,不是Thread的run方法 简单意思就是 Thread t1=new Thread(t) t1.start(); 实现方式(接口)和继承方式区别: >>避免了单继承的局限性(定义线程时候,最好采用实现的方式) >>实现的方式实现了资源的独立共享 对于继承Thread:线程代码存放在Thread子类的run方法中对于实现,是存放在接口的子类的run方法中 ______________________________________________________________________________________________________________________________________________________________________线程具有默认的名称
>>getName(); >>默认的格式 Thread_编号(0开始) >>thread.currentThread==this.getName(); 静态的,获取当前线程对象 >>setName或者构造函数(Thread(String name){super(name);}) _______________________________________________________________________________________________________________________________________________________________________多线程容易产生安全问题
>>模拟多线程的安全问题的产生 >> //try{Thread.sleep(10);}case(Exception e){} >>产生问题的原因: >>当多条语句在操作同一线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的失误 >>解决办法: >>对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不能参与执行。 >>同步代码块可以解决这个问题 >>synchronized(对象){ 需要被同步的代码块(那些语句在操作共享数据代码) } >>同步代码块中的对象如锁,持有锁的线程可以在同步中执行 没有持有锁的线程即使获得cpu的执行权,也进不去,因为没有获取锁, >>同步函数也可以解决这个问题 >>public synchronized void add(){函数体}同步的前提:
>>必须要有两个或者两个以上的线程 >>必须是多个线程使用同一个锁(即使操纵同一个共享数据)好处:
>>解决了多线程的安全的问题弊端:
>>较为消耗了资源,程序变得比较慢(因为每次都需要判断锁) ______________________________________________________________________________________________________________________________________________________同步函数是怎么实现锁的功能,有是用什么锁控制多线程的呢?
>>因为函数被对象调用,那么谁调用这个函数,那么这个锁就是该对象的锁,所以同步函数的锁就是this >>可以通过一个写同步代码块,一个用同步函数,来实现判断同步函数是不是this >>如果不出现错误的票,即使使用同一个锁 >>static synchronized void show()使用的锁是class字节码对象(Tick.class) class Ticket implements Runnable{ private /*static*/ int tick=100; boolean flag=true; //为同步代码块提供的对象 //object obj=new object(); public void run(){ while(tick>0){ //模拟多线程出现安全隐患 //try{Thread.sleep(10);}case(Exception e){} //可以这个解决多线程出现安全隐患 if (flag){ //synchronized(obj)-->synchronized(this) synchronized(this){ try{Thread.sleep(10);}case(Exception e){} if(tick>0){ System.out.println(Thread.currentThread().getName()+" "+"Runnable sale:"+tick--); } } }else{show()} } } } public synchronized void show{ if(tick>0){ System.out.println(Thread.currentThread().getName()+" "+"show sale:"+tick--); } }public class TicketDemo{
public static void main(String args[]){ Ticket t=new Ticket(); Thread t1=new Thread(t); Thread t2=new Thread(t);t1.start();
try{Thread.sleep(10);}catch(Exception e){} t.flag=flase; t2.start();}
}
________________________________________________________________________________________________________________________________________________________
>>static synchronized void show()使用的锁是class字节码对象(Tick.class)
class Ticket implements Runnable{
private static int tick=100; boolean flag=true; //为同步代码块提供的对象 //object obj=new object(); public void run(){ while(tick>0){ //模拟多线程出现安全隐患 //try{Thread.sleep(10);}case(Exception e){} //可以这个解决多线程出现安全隐患 if (flag){ //synchronized(obj)-->synchronized(Tick.class) synchronized(Tick.class){ try{Thread.sleep(10);}case(Exception e){} if(tick>0){ System.out.println(Thread.currentThread().getName()+" "+"Runnable sale:"+tick--); } } }else{show()} } } } public static synchronized void show{ if(tick>0){ System.out.println(Thread.currentThread().getName()+" "+"show sale:"+tick--); } }public class TicketDemo{
public static void main(String args[]){ Ticket t=new Ticket(); Thread t1=new Thread(t); Thread t2=new Thread(t);t1.start();
try{Thread.sleep(10);}catch(Exception e){} t.flag=flase; t2.start();}
}
____________________________________________________________________________________________________________________________________________________
//单例设计
>>饿汉式 class single{ private static void final single sin=new single(); privaate Single(){} public static single getInstance(){ return s; } }//懒汉式
class single{ private static single sin=null; private single(){} public static single getInstance(){ if(s==null){s=new single();} return s; } } // __________________________________________________________________________________________________________________________________________________________________//死锁
>>同步中嵌套同步式出现死锁的原因 class Test implements Runnable{ private boolean flag; Test(boolean flag){this.flag=flag} public void run(){ if(falge){ synchronized(mylock.locaka){ System.out.prinlnt("if locaka"); synchronized(mylock.locakb){ System.out.prinlnt("if locakb"); } }else{ synchronized(mylock.locakb){ System.out.prinlnt("else locakb"); synchronized(mylock.locaka){ System.out.prinlnt("else locaka"); } } } }class mylock{
static Object locka=new Object(); static Object locka=new Object(); }public class DeadLockTest{
public static void main(){ Thread t1=new Thread(new Test(true)); Thread t2=new Thread(new Test(false)); t1.start(); t2.start(); }}
____________________________________________________________________________________________________________________________________________线程间的通信
>>等待唤醒机制
>>wait; notify(); notifyAll();都使用在同步中,因为要对持有监视器(锁)的线程操作 所以要使用在同步中,因为只有同步中这才有具有锁为什么这些操作线程的方法要定义Object类中呢? >>因为这些方法在操作同步线程时,都必须要标识他们所操作线程只有锁 只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒 不可以对不同锁中的线程进行唤醒,也就是说等待和唤醒必须时同一个锁,而锁可以时任意对象, 所以可以被任意对象调用的方法定义Object类中 jdk升级了多线程解决锁和唤醒机制 >>lock代替了synchroinzed >>condition对像代替了notify和wait以及notifyAll的Object对象 ________________________________________________________________________________________________________________停止线程
>>如何停止线程能,只有一种方法停止,run结束 开启多线程运行,通常都是循环结构,只要控制循环,就可以让线程run()结束//run方法结束停止线程 //通过控制循环的标签来控制run的结束//但是有一种情况 //当线程处于冻结的状态,线程就不会结束,可以用interrupt恢复运行状态,这样在catch里将循环的状态变成flag=false,就可以结束run()[线程] _____________________________________________________________________________________________________________________________________守护线程
>>后台线程(即是守护线程)当所有的前台线程(主线程)结束后,后台线程自动结束 >>使用守护线程,必须要在开启线程前,使用t1.setDaemon(true);_________________________________________________________________________________
join加入线程
>>意思是当使用线程.jion时候,cpu的执行权就会交给申请的线程运行————————————————————————————————————————
线程的优先级 >>线程.setPriority(Thread.MAX_PRIORITY);1-10级 >>Thread.yield :临时暂停,可以达到线程的交替使用 ——————————————————————————————————————线程的应用场景
>>当某些代码需要同是被执行时,用线程进行封装。 匿名内部类的写法 new Thread(){ public void run(){}
}.start();