多线程

来源:互联网 发布:男朋友是java工程师 编辑:程序博客网 时间:2024/05/29 08:55

首先我们来了解一下概念
进程:是一个正在执行的程序,每一个进程执行都有一个顺序,该顺序是一个执行路径,或者叫一个控制单元。
线程:就是进程中的一个独立的控制单元,线程在控制着进程的执行。
一个进程中至少有一个线程。
Java VM 启动的时候会有一个进程java.exe
该进程中至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中,该线程称之为主线程。
另:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。
多线程存在的意义:使用线程可以把占据时间长的程序中的任务放到后台去处理;用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度;程序的运行速度可能加快;在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了,在这种情况下可以释放一些珍贵的资源如内存占用等等。
线程的创建方式:
通过对API的查找,java已经提供了对线程这类事务的描述,就是Thread类,
创建线程的第一种方式,继承Thread类
步骤:
1.定义类继承Thread类
2.复写Thread类中的run方法,目的:把自定义要运行多线程的代码写入run方法中
3.调用线程的start方法,该方法的作用:启动线程,调用run方法
为什么要复写run方法?
Thread类用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法,也就是说,Thread类中的run方法,用于存储线程要运行的代码
发现每次运行结果都不同,因为多个线程都获取cpu的执行权,cpu执行到谁,谁就运行。
明确一点,在某一时刻,只能有一个程序在运行,多核除外。
cpu在做着快速切换,以达到看上去同时运行的效果。
我们可以形象的把多线程的运行行为看成是互相抢夺cpu的执行权

package first;public class ThreadTest {    public static void main(String[] args) {        ThreadDemo thread=new ThreadDemo();//创建好一个线程        thread.start();        //thread.run()//这样也可以运行,但没有多线程的效果,是先后运行的了        for(int i=0;i<10;i++){            System.out.println("main Run---->"+i);            try {                Thread.sleep(50);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}class ThreadDemo extends Thread{    public void run() {//复写run方法        for(int i=0;i<10;i++){            System.out.println("Thread Run*****"+i);            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

线程的五种状态图:
这里写图片描述
冻结状态:又分为睡眠和等待两种状态。
临时状态:调用了start方法后,还在等待cpu来处理启动
冻结状态和临时状态的区别是,是否有执行权。
创建线程的第二种方式:
需求:简单的卖票程序,实现多个窗口同时卖票
1.定义类,实现Runnable借口
2.覆盖Runnable接口中的run方法
:将线程要运行的代码存放在run方法中
3.通过Thread类建立线程对象
4.将Runnable借口的子类对象作为实际参数传递给Thread的构造函数
:为什么要将Runnable借口的子类对象传递给Thread的构造函数?
因为自定义的run方法所属的对象是Runnable借口的子类对象,
所以要让线程去运行指定对象的run方法,就必须明确该run方法所属对象
5.调用Thread类的start方法开启线程并调用Runnable借口子类的run方法

package first;  class Ticket implements Runnable{ //extends Thread{       //如果是静态的话,所有的线程会共享这100张票      /*private  static int  ticket =100;*/        //如果不是静态的话,每一个线程对象都会创建这个ticket对象,也即每个线程拥有100张票卖。      //这时候,如果还是采用继承Thread类的方法就不行了,需要使用实现Runnable接口创建线程      private  int  ticket =1000;      //定义一个对象,为同步使用,任意          Object obj= new Object();         public void run() {          //在这里声明的对象是无效的          /*Object obj= new Object(); */          while(true){              synchronized (obj) {                  if(ticket>0){                          try {                          Thread.sleep(10);                      } catch (InterruptedException e) {                          e.printStackTrace();                      }                      System.out.println(Thread.currentThread().getName()+".....sale : "+ ticket--);                  }              }          }      }   }  public class TicketDemo {      public static void main(String[] args) {          Ticket t = new Ticket();          Thread t1 = new Thread(t);          Thread t2 = new Thread(t);          Thread t3 = new Thread(t);          Thread t4 = new Thread(t);          t1.start();          t2.start();          t3.start();          t4.start();           }  }  

实现 方式和继承方式的区别:
实现方式的好处:避免了继承方式的单继承的局限性
在定义线程时,建议使用实现方式
继承Thread的线程代码存放在Thread子类的run方法中
实现Runnable线程代码存放在借口的子类run方法中

下面有一个需求:
银行有一个金库,有两个储户分别存300元,每次存一百,存3次

package first;/* * 1.要明确哪些代码是多线程运行代码 * 2.哪些数据是共享数据 * 3.明确多线程运行代码中哪些语句是操作共享数据的 */public class BankDemo {    public static void main(String[] args) {        Cus cus1=new Cus();        Cus cus2=new Cus();        Thread t1=new Thread(cus1);        Thread t2=new Thread(cus2);        t1.start();        t2.start();    }}class Bank{    private int sum;    public synchronized void add(int n,String name){//同步函数        sum+=n;        System.out.println(name+" sum="+sum);    }}class Cus implements Runnable{    Bank b=new Bank();    @Override    public void run() {        for(int i=0;i<3;i++)            b.add(100,Thread.currentThread().getName());    }}

单例设计模式

//饿汉式class Single{    private static final Single s=new Single();    private Single(){}    public static Single getInstance(){return s;}}//懒汉式//实例的延迟加载,但在多线程时会出错,要加锁class Single{    private static Single s=null;    private Single(){}    private static Single getInstance(){        if(s==null){            synchronized(Single.class){                if(s==null){                    s=new Single();                }            }        }        return s;    }}

下面来一个简单的死锁程序作为结束:
死锁:简单的讲就是a需要b的资源,同时b也需要a的资源,然后两个进程就在等待,发生了死锁

package first;/* * 死锁 */public class DeadLockDemo {    public static void main(String[] args) {        Thread t1=new Thread(new TestDeadLock(true));        Thread t2=new Thread(new TestDeadLock(false));        t1.start();        t2.start();    }}class TestDeadLock implements Runnable{    private boolean flag;    public TestDeadLock(boolean flag) {        this.flag=flag;    }    @Override    public void run() {        if (flag) {            synchronized (MyLock.locka) {                System.out.println("if locka");                synchronized (MyLock.lockb) {                    System.out.println("if lockb");                }            }        }else{            synchronized (MyLock.lockb) {                System.out.println("else lockb");                synchronized (MyLock.locka) {                    System.out.println("else locka");                }            }        }    }}class MyLock{    static Object locka=new Object();    static Object lockb=new Object();}

谢谢!

0 0
原创粉丝点击