多线程技术概述 每个线程都有自己的栈空间,并用一份堆内存1。同步和异步 同步:排队执行,效率低但是安全。 异步:同时执行,效率高但是数据不安全。2。并发与并行 并发:指两个或多个时间在同一个时间段内发生。 并行:指两个或多个时间在同一时刻发生(同时发生)3。执行步骤,有利于理解线程时用来做什么的publicclassTest{publicstaticvoidmain(String〔〕args)throwsInterruptedException{1。创建一个任务对象Xianchengx1newXiancheng();2。创建一个线程,并为其分配一个任务ThreadtnewThread(x1);3。执行这个线程t。start();}}4。多用Runnable 5。线程对象可以打标记packagecom。kkb;publicclassDemo01ThreadInterrupt{publicstaticvoidmain(String〔〕args){ThreadtnewThread(newMyThings());t。start();for(inti0;i5;i){System。out。println(Thread。currentThread()。getName()i);try{Thread。sleep(1000);}catch(InterruptedExceptione){e。printStackTrace();}}t。interrupt();给线程添加标记}}classMyThingsimplementsRunnable{Overridepublicvoidrun(){for(inti0;i10;i){System。out。println(Thread。currentThread()。getName()i);try{Thread。sleep(1000);}catch(InterruptedExceptione){中断异常如果这个事物正在执行的线程有了中断标记,那么就进入到catch块中System。out。println(虽然我添加了标记来到了这里,但是,你没有让我死亡哈哈哈哈);加上return资源就释放了System。out。println(添加了interrupt标记,后面返回return,我结束了);return;}}}}6。守护线程 线程:分为守护线程和用户线程 用户线程:当一个进程不包含任何的存货线程时,进程结束 守护线程:守护用户的线程,当最后一个用户线程结束时,所有守护线程自动死亡packagecom。kkb;publicclassDemo01ThreadInterrupt{publicstaticvoidmain(String〔〕args){ThreadtnewThread(newMyThings());t。setDaemon(true);设置t为守护线程,当这个应用(进程中最后一个用户线程死亡的时候,守护线程自动死亡)t。start();for(inti0;i5;i){System。out。println(Thread。currentThread()。getName()i);try{Thread。sleep(1000);}catch(InterruptedExceptione){e。printStackTrace();}}t。interrupt();给线程添加标记}}classMyThingsimplementsRunnable{Overridepublicvoidrun(){for(inti0;i10;i){System。out。println(Thread。currentThread()。getName()i);try{Thread。sleep(1000);}catch(InterruptedExceptione){中断异常如果这个事物正在执行的线程有了中断标记,那么就进入到catch块中System。out。println(虽然我添加了标记来到了这里,但是,你没有让我死亡哈哈哈哈);加上return资源就释放了System。out。println(添加了interrupt标记,后面返回return,我结束了);return;}}}}7。线程安全问题 概述:为什么会导致线程不安全:首先假定一种情况:当事物中余票为1时,三个线程进入来买票1。A线程:看到conut0,进入,正在出票的时候,count还没来得及做数据的变更操作2。B线程:这个时候,B也进来了,因为conut还没有变更。。。。。这就是多线程,进入产生时间偏的问题这里为了更好的模拟实际中的放票状态,就引入了一个Thread。sleep,使线程进行休眠的操作packagecom。kkb;为什么会导致线程不安全:首先假定一种情况:当事物中余票为1时,三个线程进入来买票1。A线程:看到conut0,进入,正在出票的时候,count还没来得及做数据的变更操作2。B线程:这个时候,B也进来了,因为conut还没有变更。。。。。这就是多线程,进入产生时间偏的问题这里为了更好的模拟实际中的放票状态,就引入了一个Thread。sleep,使线程进行休眠的操作publicclassUnSafe{publicstaticvoidmain(String〔〕args){RunnablernewTicket();Threadt1newThread(r);Threadt2newThread(r);Threadt3newThread(r);t1。start();t2。start();t3。start();}staticclassTicketimplementsRunnable{privateintconut10;Overridepublicvoidrun(){while(conut0){System。out。println(正在准备卖票);try{Thread。sleep(1000);}catch(InterruptedExceptione){e。printStackTrace();}conut;System。out。println(余票:conut);}}}}8。synchronized锁 注意:看同一把锁!!!! 同步代码块和同步方法都是隐式锁1。同步代码块packagecom。kkb;所谓上锁:就是在一个线程正在执行任务时,其他的对象只能在外面排队,因为这个事物现在的情况对外是不开放的指定事物中的一个锁对象,在一个线程进入时,这个对象就会被标记上一把锁要看同一把锁publicclassSafeSynchronized{publicstaticvoidmain(String〔〕args){RunnablernewTicket();Threadt1newThread(r);Threadt2newThread(r);Threadt3newThread(r);t1。start();t2。start();t3。start();}staticclassTicketimplementsRunnable{privateintconut10;privateObjectonewObject();注意这里的o为了保证这个事物中存在一个可以上锁的对象Overridepublicvoidrun(){while(true){synchronized(o){if(conut0){System。out。println(Thread。currentThread()。getName()正在准备卖票);try{Thread。sleep(1000);}catch(InterruptedExceptione){e。printStackTrace();}conut;System。out。println(余票:conut);}else{break;}}}}}}2。设计为同步方法注意这里面锁方法的时候,锁的对象就是这个方法饿地址上加锁,一个一个进入此方法我们打印出来的this就是:com。kkb。SafeSynchronizedTomethodTicket3694916f这个方法的地址只需要在这个方法上加上synchronized进行标志packagecom。kkb;注意这里面锁方法的时候,锁的对象就是这个方法饿地址上加锁,一个一个进入此方法我们打印出来的this就是:com。kkb。SafeSynchronizedTomethodTicket3694916f这个方法的地址publicclassSafeSynchronizedTomethod{publicstaticvoidmain(String〔〕args){RunnablernewTicket();Threadt1newThread(r);Threadt2newThread(r);Threadt3newThread(r);t1。start();t2。start();t3。start();}staticclassTicketimplementsRunnable{privateintconut10;privateObjectonewObject();不需要这个对象了因为锁方法的时候锁的其实就是this,这个save方法的this注意这里的o为了保证这个事物中存在一个可以上锁的对象com。kkb。SafeSynchronizedTomethodTicket3694916fOverridepublicvoidrun(){while(true){booleansalesale();if(!sale){如果没票了就结束break;}}}publicsynchronizedbooleansale(){if(conut0){System。out。println(Thread。currentThread()。getName()正在准备卖票);try{Thread。sleep(1000);}catch(InterruptedExceptione){e。printStackTrace();}conut;System。out。println(余票:conut);System。out。println(this);}else{returnfalse;}returntrue;}}}3。显示锁LocklnewReentrantLock();packagecom。kkb;importjava。util。concurrent。locks。Lock;importjava。util。concurrent。locks。ReentrantLock;publicclassSafeSynchronizedLock{publicstaticvoidmain(String〔〕args){RunnablernewTicket();Threadt1newThread(r);Threadt2newThread(r);Threadt3newThread(r);t1。start();t2。start();t3。start();}staticclassTicketimplementsRunnable{privateintconut10;给一把显式锁privateLocklnewReentrantLock();Lock锁接口的实现类Overridepublicvoidrun(){while(true){每次一个线程进入就会加上一个锁,其他线程无法进入l。lock();加锁booleansalesale();l。unlock();解锁if(!sale){如果没票了就结束break;}}}publicbooleansale(){if(conut0){System。out。println(Thread。currentThread()。getName()正在准备卖票);try{Thread。sleep(1000);}catch(InterruptedExceptione){e。printStackTrace();}conut;System。out。println(余票:conut);}else{returnfalse;}returntrue;}}}4。公平锁和不公平锁 就是在声明显式锁的时候加上一个true。 排队一个一个进,不会出现线程争先恐后的,谁抢到就是谁的LocklnewReentrantLock(true);Thread0正在准备卖票余票:9Thread1正在准备卖票余票:8Thread2正在准备卖票余票:7Thread0正在准备卖票余票:6Thread1正在准备卖票余票:5Thread2正在准备卖票余票:4Thread0正在准备卖票余票:3Thread1正在准备卖票余票:2Thread2正在准备卖票余票:1Thread0正在准备卖票余票:09。多线程交互问题 线程的wait和线程的唤醒notifyAll 再引入一个变量交替执行10。线程池 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁的船舰线程和销毁线程需要时间。线程池就是一个可以容纳多个线程的容器,池中的线程可以反复的使用,省区了频繁创建线程对象的操作,节省了大量的时间和资源。 1。创建线程 2。创建任务 3。执行任务 4。关闭线程 1。缓存线程池 2。定长线程池 3。单线程池 4。周期定长线程池