java中的多线程

来源:互联网 发布:phpci连接不上数据库 编辑:程序博客网 时间:2024/06/08 18:27

一 创建多线程

1.1 创建多线程的方式有两种

1.1.1 第一种:自定义个类继承Thread类,重写Thread类的run方法,创建Thread的子类对象,并且调用start方法开启线程

public class ThreadDemo extends Thread{  //重写Thread的run方法  任务代码写在run方法中    @Override    public void run()     {      System.out.println("执行了一个子线程任务");       //子线程休眠1s        try {            Thread.sleep(1000);//这里不能抛出异常,只能捕获 Thread类的run方法没有抛出异常类型,所以子类不能抛出异常类型 ,子类抛出的异常类型必须是小于或等于父类的异常类型        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }       }}---------public class Main {    public static void main(String[] args) {        ThreadDemo demo = new ThreadDemo();        //调用start方法开启线程        demo.start()    }}

1.1.2 第二种(常用) : 自定义一个类实现Runnable接口,实现Runnable接口的run方法,把任务定义在run方法里,创建Runnable实现类对象,创建Thread类对象并且把Runnable实现类对象作为实参传递进去,调用Thread对象的start方法开启线程

public class ThreadDemo2 implements Runnable{  //实现Runnable接口的run方法  任务代码写在run方法中    @Override    public void run()     {      System.out.println("执行了一个子线程任务");     }}public class Main {    public static void main(String[] args) {        ThreadDemo2 td = new ThreadDemo();        Thread thread = new Thread(td);        //开启一个线程        thread.start();    }}

1.2 线程生命周期状态图

这里写图片描述

1.3 线程中的常用方法

setName(String name)  //设置线程名字(线程对象调用)getName() //获取线程的名字(线程对象调用)setPriority(int newPriority) //设置线程的优先级(最大10,最小1,默认5),线程获取cpu的概率currentThread() //返回正在执行的线程(线程类名调用)

1.4 线程安全问题

1.4.1 线程安全问题出现的原因

存在两个或两个以上的线程对象,而且线程之间共享一个资源。
有多个语句操作了共享资源

1.4.2 线程安全问题解决方案

方式一 : 同步代码块(常用)

synchronized(锁对象) //注:锁对象可以是任意的对象(一般用this),锁对象的内部维护了一个状态,标识锁是开的还是关的
{
//需要被同步的代码(所有处理公共资源有关的代码)
}

    @Override    public void run()     {      while(true)      {         synchronized(this)          {            if (num>0)            {             num--             System.out.println("执行了一个子线程任务");            }          }       }

方式二 : 同步函数

同步函数就是使用synchronized修饰一个函数

同步函数注意事项 : 非静态的同步函数的对象是this,静态的同步函数的锁对象是类的字节码文件(class对象)

//非静态同步函数public synchronized void run() {  //操作公共资源的代码}//静态同步函数public synchronized static void getMoney(){  //操作公共资源的代码}

1.5 线程之间通讯

经典例子 : 生产者和消费者
wait() : 等待,等待状态下的线程必须被其他线程调用notify方法才能唤醒
notify(): 唤醒 ,唤醒等待的线程

wait与notify方法要注意的事项:

wait方法与notify方法是属于Object对象的
wait方法与notify方法必须要在同步代码块或者同步函数中才能使用
wait方法与notify方法需要由锁对象调用

package Main;public class ThreadTest {    public static void main(String[] args) {        produce p = new produce();        Producer pro = new Producer(p);        Customer cus = new Customer(p);        Thread proThread = new Thread(pro);        Thread cusThread = new Thread(cus);        proThread.start();        cusThread.start();     }}//产品class produce {    int number;//产品编号    boolean flag;//标识是否生产完成}//生产者class Producer implements Runnable {    produce p ;    public Producer(produce p) {        super();        this.p = p;    }    @Override    public void run() {        // TODO Auto-generated method stub        while (p.number<100)         {           synchronized (p)            {               if(p.flag==false)               {                   p.number++;                   System.out.println("生产了第"+p.number+"个");                        p.flag = true;//标识 已经生产了一个                        p.notify();//生产完成一个 唤醒消费者去消费               }               else               {                   try {                    p.wait();//还没有消费 等待消费者去消费                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }               }            }        }    }}//消费者class Customer implements Runnable {   produce p;   public Customer(produce p)    {        this.p = p;    }    @Override    public void run() {        // TODO Auto-generated method stub        while(p.number<100)        {          synchronized (p)           {              if(p.flag==true)              {                  System.out.println("消费了第"+p.number+"个");                   p.flag = false; //标识已经消费完了一个                   p.notify();//消费完了一个 唤醒生产者去生产              }              else              {                 try {                    p.wait(); //产品还没有生产出来  要等待                 } catch (InterruptedException e) {                    e.printStackTrace();                }              }           }        }    }}

1.6 后台线程(守护线程)

一个线程如果需要随着主线程的存在而存在,随着主线程的消亡而消亡,就可以把这个线程设为守护线程。

把线程设为守护线程的方法:

Customer cus = new Customer(p);     Thread proThread = new Thread(pro);proThread.setDaemon(true);// 设置线程是否为守护线程,true为守护线程proThread.start();
原创粉丝点击