Java——多线程

多线程的创建

方式一:继承Thread类(不能返回线程执行结果)

——1.定义一个线程类继承Thread类

——2.重写run方法,定义线程要干啥

——3.new 一个线程对象

——4.调用start方法启动线程(执行run方法)

实例:

 package DemoCreate;
 /*
 //1.定义一个线程类继承Thread类
  */
 public class MyThread extends Thread
 {
     //2.重写run方法,定义线程要干啥
     @Override
     public void run() {
         for (int i = 0 ; i< 100;i++){
             System.out.println("子线程执行输出"+i);
         }
     }
 }
 ​
 public class ThreadDemo1 {
     public static void main(String[] args) {
     //3.new  一个线程对象
         Thread t = new MyThread();
         /*
         4.调用start方法启动线程(执行run方法)
             这里不能直接调用run,否则会被当成普通方法执行,相当于单线程
          */
         t.start();
         for (int i = 0;i<100;i++){
             System.out.println("主线程执行输出"+i);
         }
     }
 }

方式二:实现Runnable接口(不能返回线程执行结果)

——1.定义一个线程任务类,实现Runnable接口

——2.重写run方法,定义线程的执行任务

——3.创建一个任务对象(实现Runnable接口)

——4.将任务对象交给Thread处理

——5.启动线程

实例:

 public class MyRunnable implements Runnable{
       /*
         2.重写run方法,定义线程的执行任务
      */
     @Override
     public void run() {
        for (int i = 0;i < 100;i++){
            try {
                Thread.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"子线程执行输出"+i);
        }
     }
 ​
 }
 ​
 public class ThreadDemo2 {
     public static void main(String[] args) {
         //3.创建一个任务对象
         Runnable r = new MyRunnable();
         //4.将任务对象交给Thread处理
         Thread t = new Thread(r,"hja");
         //5.启动线程
         t.start();
         try {
             t.join(200);
 ​
         } catch (Exception e) {
             e.printStackTrace();
         }
         for (int i = 0 ; i<100 ; i++){
             System.out.println("主线程执行输出"+i);
         }
     }
 }

方式三:利用Callable、FutureTask接口实现

——1.定义一个任务类 实现Callable接口(因该声明线程任务执行完毕后的结果的数据类型)

——2.重写cal方法(线程的任务方法)

——3.创建Callable任务对象

——4.把Callable(不能直接交给Thread)任务对象 交给FutureTask (实现的是Runnable接口可以交给Thread)对象

——5.交给线程处理

——6.启动线程

实例:

 public class ThreadDemo3 {
     public static void main(String[] args) {
         /*
             3.创建Callable任务对象
          */
         Callable<String> call = new MyCallable(100);
         //4.把Callable任务对象 交给FutureTask 对象
         //  FutureTask对象 相当于 Runnable对象(实现Runnable接口) 可以交给Thread
         // FutureTask对象 可以在线程结束之后通过调用get方法得到线程执行后结果
         FutureTask<String> f = new FutureTask<>(call);
         //5.交给线程处理
         Thread t = new Thread(f);
         //6.启动线程
         t.start();
 ​
         Callable<String> call1 = new MyCallable(200);
         FutureTask<String> f1 = new FutureTask<>(call1);
         Thread t1 = new Thread(f1);
         t1.start();
 ​
         try {
             String rs = f.get();
             System.out.println("第一个结果:"+rs);
         } catch (Exception e) {
             e.printStackTrace();
         }
 ​
         try {
             String rs1 = f1.get();
             System.out.println("第二个结果:"+rs1);
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 }
 ​
 public class MyCallable implements Callable <String>{
     private int n ;
 ​
     public MyCallable(int n) {
         this.n = n;
     }
     /*
         2.重写cal方法(线程的任务方法)
      */
 ​
     @Override
     public String call() throws Exception {
         int sum = 0;
         for (int i = 0; i <= n ; i++){
             sum +=i;
         }
         return "子线程执行的结果是:"+sum;
     }
 }

线程的状态转换

线程状态相关方法

——设置线程名称

Thread t = new Thread(线程名);

Thread t = new Thread(实现Runnable接口类的对象, 线程名称);

Thread t = new Thread(); t.setName(线程名称);

——获取线程名称

     Thread子类中 getName

String name = Thread.currentThread().getName();

——判断线程是否启动(是否调用start)

isAlive

——线程合并

join

——线程的暂停

yield

——线程的(睡眠)暂停

sleep

线程同步

线程安全问题

——竞态条件当多个线程读写共享资源时,就称存在竞态条件;

——一段代码如果对共享资源的多线程读写操作,这段代码就被称为临界区;

解决方式:

——加synchronized锁

——加Lock锁

售票案例引入:

 package DemoCreate;
 /*
    多线程的创建方式二:实现Runnable接口
  */
 public class SellTicket implements Runnable{
     private int ticket = 100;
     //定义锁住的对象
     方式一:private Object object = new Object();
     方式二:Lock lock = new ReentrantLock();
     public static void main(String[] args) {
         //3.创建一个任务对象
         SellTicket r = new SellTicket();
         //4.将任务对象交给Thread处理
         Thread t = new Thread(r,"窗口一");
         Thread t1 = new Thread(r,"窗口二");
         Thread t2 = new Thread(r,"窗口三");
         //5.启动线程
         t.start();
         t1.start();
         t2.start();
     }
     
     //锁方法
      public  synchronized void SellTicket(){
         if (ticket > 0) {
             try {
                 Thread.sleep(200);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             System.out.println("正在出售" + ticket + "张票");
             ticket--;
         }
     }
     
     
     
     @Override
     public void run() {
         //线程不安全
         while (true) {
             //解决方式一:synchronized 锁住的是一个对象  锁代码块
             synchronized (object) {
                 if (ticket > 0) {
                     try {
                         Thread.sleep(200);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                     System.out.println("正在出售" + ticket + "张票");
                     ticket--;
                 }
             }
             
             //解决方式一:synchronized 锁方法体
              while (true) {
             this.SellTicket();
             
             }
             //解决方式二:加Lock锁
             try {
                 lock.lock();//上锁
                 if (ticket > 0) {
                     try {
                         Thread.sleep(200);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                     System.out.println("正在出售" + ticket + "张票");
                     ticket--;
                 }
             } catch (Exception e) {
                 e.printStackTrace();
             } finally {
                 lock.unlock();//开锁
             }
         }
     }
 }

Lock&synchronized

Locksynchronized
显式锁(手动开启和关闭锁)隐式锁,出了作用域自动释放
只有代码块锁有代码块锁和方法锁
性能更好,并且具有更好的扩展性

优先使用顺序:Lock > synchronized块 > synchronized方法;

死锁问题

死锁发生的四个必要条件:

——互斥使用

——不可抢占

——请求和保持

——循环等待

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值