并发-----java多线程理解与总结

来源:互联网 发布:淘宝自动浏览软件app 编辑:程序博客网 时间:2024/06/08 11:08

------- android培训、java培训、期待与您交流! ----------

多线程Thread:一个进程中拥有多个可执行路径,一个程序至少有一个进程,而一个进程至少有一个线程;

java对多线程的支持方案:1继承Thread类,2实现Runnable方法

特点:由于线程是程序的多条执行路径,所以执行权CPU说了说,多线程具有随机性和并发性

Thread类概述:

  1. run()方法概述:这个方法里封装了线程要执行的代码,也就是说我们将想要多线程执行的代码的地方,如果对象直接调用则不是多线程;
  2. start()方法:让线程就绪,执行run()方法体;
  3. 在线程就绪前,也就是start()调用前,我们可以设置线程的优先级,守护线程等,易于理解
  4. isLive()测试线程是否是激活状态
  5. interrupt(),中断线程
  6. thread类试图通过自己的方法来控制线程合理的在理想状态下执行,但是cpu的多核多线程技术使得他不可能理想的完成,所以,其他的方法就看api了解
  7. 线程的生命周期图

cpu操作是具有原子性的,所以判断线程时候存在问题的条件为:

  • 是否是多线程 ,这个必须是,因为我们编写的就是多线程程序
  • 是否有共享代码,从这一步就要考虑问题的存在了,因为每个线程都有自己的栈内存,程序计数器等
  • 是否是同一把锁,这个往往被忽略,但是jdk5出现的显示的锁,一般这一步不会出错了;
  • 是否有多条语句操作共享语句,解决问题的根本所在了

解决问题的方法:同步代码块,同步方法。前提:多线程,同一把锁

格式: 1synchronized(对象){}        2public synchronized void  方法名(){}

还是卖票吧,只不过我将飘封装称了类,稍微有点不同

1票类:

<span style="white-space:pre"></span>public class Ticket {//张数private int number;//票价private float price;public Ticket(int number) {this.number=number;}//get  set省略
2卖票具体线程类:

public class SaleTicke implements Runnable {private Ticket t;public SaleTicke(Ticket t) {this.t = t;}@Overridepublic void run() {//这个不是共享数据//int sx=t.getNumber(),并且用sx来判断,各自的栈内存都会有这么一个变量,所以会出现卖200张票while (true) {
<span style="white-space:pre"></span>//将所有操作的资源的语句全部用同步代码块包裹synchronized (this) {if (t.getNumber() > 0) {System.out.println(Thread.currentThread().getName()+ "出售了第" + (t.getNumber()) + "张票");//卖一张,减少一张,就这里不同t.setNumber(t.getNumber() - 1);} else {break;//run()方法结束,线程结束,jvm结束}}}}}

3卖票测试类:
<span style="white-space:pre"></span>public static void main(String[] args) {Ticket resource =new Ticket(100);SaleTicke st=new SaleTicke(resource);Thread t1=new Thread(st,"窗口-1");Thread t2=new Thread(st,"窗口-2");t1.start();t2.start();}
4卖票总结:当票被封装为类时,第二种安全因素就诞生了,以及在取出值之后要调用set方法来重新设置

5线程间通信:等待唤醒机制,运用jdk5新特性,生产者,消费者

/** *资源类 */public class Resource {//资源名private String name;//数量private int count=0;//标记private boolean flag=false;//锁private Lock lock=new ReentrantLock();private Condition set=lock.newCondition();public Resource(){}//创造资源public void creatResource() throws InterruptedException{lock.lock();try {//if只判断一次,在这里用不合适while(flag)//有,等set.await();++count;System.out.println(Thread.currentThread().getName()+"-----生产第"+count+"个商品");//重置标记flag=true;//唤醒set.signal();} finally{lock.unlock();}}//消费public void useRes() throws InterruptedException{lock.lock();try {while(!flag)//没有,等set.await();System.out.println(Thread.currentThread().getName()+"正在消费第" + count + "商品");//重置标记flag=false;//唤醒set.signal();} finally{lock.unlock();}}}
/** * 生产者 */public class Creat implements Runnable{private Resource r=null;public Creat(Resource r){this.r=r;}public Creat(){}@Overridepublic void run() {while(true){try {r.creatResource();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
/** * 消费者 */public class Use implements Runnable{private Resource r = null;public Use(Resource r) {this.r = r;}public Use() {}@Overridepublic void run() {while(true){try {r.useRes();} catch (InterruptedException e) {e.printStackTrace();}}}}
/** * 测试类 */public class UseTest {public static void main(String[] args) {Resource r=new Resource();Creat c=new Creat(r);Use u=new Use(r);new Thread(c,"生产者").start();new Thread(u,"消费者").start();}}

结果:
生产者-----生产第26911个商品消费者正在消费第26911商品生产者-----生产第26912个商品消费者正在消费第26912商品生产者-----生产第26913个商品消费者正在消费第26913商品生产者-----生产第26914个商品消费者正在消费第26914商品生产者-----生产第26915个商品消费者正在消费第26915商品生产者-----生产第26916个商品消费者正在消费第26916商品生产者-----生产第26917个商品消费者正在消费第26917商品生产者-----生产第26918个商品消费者正在消费第26918商品生产者-----生产第26919个商品消费者正在消费第26919商品生产者-----生产第26920个商品消费者正在消费第26920商品

死锁:锁嵌套使用导致

public class DieLock {public static void main(String[] args) {new MyThread(true).start(); new MyThread(false).start(); }}class Lock {public static final Object lock1 = new Object();public static final Object lock2 = new Object();}class MyThread extends Thread {private boolean flag = false;MyThread(boolean b){this.flag=b;}public void run() {if (flag) {//锁1嵌套锁2synchronized (Lock.lock1) {System.out.println("锁1.....");synchronized (Lock.lock2) {System.out.println("锁12..........");}}} else {//锁2嵌套锁1synchronized (Lock.lock2) {System.out.println("锁2||||||||");synchronized (Lock.lock1) {System.out.println("锁22||||||||||||");}}}}}

总结:

1清楚的讲,多线程让我的头大了许多,非常不理解为什么会出错,调试比较难受,啊,真的炸了,最后,一步步分析,判断,找出问题出现的地方并且对症下药才可以;

2那四个判断条件是多么的重要:在写一次

  • 是否是多线程 (是否同时加锁),这个必须是,因为我们编写的就是多线程程序
  • 是否有共享代码,从这一步就要考虑问题的存在了,因为每个线程都有自己的栈内存,程序计数器等
  • 是否是同一把锁,这个往往被忽略,但是jdk5出现的显示的锁,一般这一步不会出错了;
  • 是否有多条语句操作共享语句,解决问题的根本所在了

------- android培训、java培训、期待与您交流! ----------

0 0