javaDay06-多线程

Thread

实现1:

继承Thread类,重写run方法。

 MyThread th = new MyThread();
 th.start()

实现2:

实现Runable接口,从写run方法,创建子类对象。传入Thread类的

MyRunable myRunable = new MyRunable();
Thread th = new Thread(myRunable);
th.start();

实现3:

实现 Callable 接口。 (相较于实现 Runnable 接口的方式,方法可以有返回值,并且可以抛出异常)

  1. 创建一个类实现Callable 任务接口
  2. 创建一个FutureTask类将Callable接口的子类对象作为参数传进去
  3. 创建Thread类, 将FutureTask对象作为参数传进去
  4. 开启线程*/
		FutureTask<Object> task = new FutureTask<>(myCallable);
        Thread th = new Thread(task);
        th.setName("线程A");
        th.start();
        //task里的get方法可以获取到返回值
        Object o = task.get();
        System.out.println(o);

方法:

  1. public final int getPriority()返回线程的优先级。默认为5
  2. public final void setPriority(int newPriority)
  3. public static void sleep(long millis)
  4. public final void join()等待该线程执行完毕了以后,其他线程才能再次执行
  5. public static void yield(): (礼让)暂停当前正在执行的线程对象,并执行其他线程
  6. public final void setDaemon(boolean on)守护线程
  7. public final void stop()
  8. public void interrupt()

案例:卖电影票

public class CellThread extends Thread {
    //定义一个静态常量被3个线程所共享
    static int piao=100;
    @Override
    public void run() {
        while (true) {
            if (piao > 0) {
                System.out.println(this.getName() + "抢到了第" + (piao--) + "票");
            }
        }
    }
}

public class MyTest {
    public static void main(String[] args) {
      /*  A:
        案例演示
        需求:某电影院目前正在上映贺岁大片,共有100张票,而它有3个售票窗口售票,请设计一个程序模拟该电影院售票。
        通过继承Thread类实现*/
        //100张票 属于共享资源,三个窗口共同卖
        //三个窗口就相当于三个线程。
        CellThread th1 = new CellThread("窗口1");
        CellThread th2 = new CellThread("窗口2");
        CellThread th3 = new CellThread("窗口3");
        th1.start();
        th2.start();
        th3.start();
    }
}

线程安全问题------同步与锁

sychronized

  • 语法:
sychronized(对象){
同步代码;
}
  • 一个对象一把锁。互斥锁。将这个对象定义为static。
  • 同步方法:方法前加sychronized关键字,锁对象是this

Lock

子类:ReentrantLock();
方法:lock()+unlock()
典型使用:

class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() { 
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

死锁:相互等待

public interface LockUtils {
    //定义锁对象A
    public static final Object objA = new Object();
    //定义锁对象B
    public static final Object objB = new Object();

}

public class MyRunnable implements Runnable {
    private boolean flag;

    public MyRunnable(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag) {
            synchronized (LockUtils.objA) {
                System.out.println("true线程持有A锁,进来了");
                synchronized (LockUtils.objB) {
                    System.out.println("true线程持有B锁,进来了");
                }
            }
        }
        else{
            synchronized (LockUtils.objB){
                System.out.println("false线程持有B锁,进来了");
                synchronized (LockUtils.objA){
                    System.out.println("false线程持有A锁,进来了");
                }
            }
        }
    }
}


public class MyTest {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable(true);
        Thread th1 = new Thread(myRunnable);

        MyRunnable myRunnable1 = new MyRunnable(false);
        Thread th2 = new Thread(myRunnable1);

        th1.start();
        th2.start();


    }
}

等待唤醒机制:

  • void wait () 在其他线程调用此对象的 notify () 方法或 notifyAll () 方法前,导致当前线程等待。

  • void wait (long timeout) 在其他线程调用此对象的 notify () 方法或 notifyAll ()方法,或者超过指定的时间量前,导致当前线程等待。

  • void notify () 唤醒在此对象监视器上等待的单个线程。

  • void notifyAll () 唤醒在此对象监视器上等待的所有线程。

案例:

//生产线程
public class SetThread extends Thread {

    private Food food;
    public SetThread(Food food) {
        this.food = food;
    }
    int i=0;

    @Override
    public void run() {
         while(true){
             //将共享资源的对象设置为锁对象
             synchronized (food){
                 if(Food.flag){
                     //作为生产线程有资源就进行等待
                     try {
                         food.wait();
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }

                 }

                     if (i % 2 == 0) {
                         food.name = "包子";
                         food.price = 2;
                     } else {
                         food.name = "菜加馍";
                         food.price = 4;
                     }

                 //进行修改标记
                 Food.flag=true;
                 //唤醒消费线程,让消费线程进行消费
                 food.notify();

             }
             i++;
         }
    }
}


//消费线程
public class GetThread  extends Thread{
    private Food food;
    public GetThread(Food food) {
        this.food = food;
    }

    @Override
    public void run() {
        while(true){
            synchronized (food){
                if(!Food.flag){
                    //消费线程没有资源就进行等待
                    //在调用wait()方法之前,线程必须获得该对象的对象级别锁
                    //即只能在同步代码块或者同步方法中进行调用
                    //wait()方法使得当前线程状态处于阻塞状态,直到被另外一个线程调用notify()方法进行唤醒。
                    try {
                        food.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //消费资源
                System.out.println("食物的品种为:"+food.name+"===="+"食物的价格为:"+food.price+"元");
                //当没有资源时(即将资源标记置为false)
                Food.flag=false;
                //通知生产线程进行生产
                //notify()方法需要在同步方法与同步代码块中进行调用
                //即在调用前,线程也必须得到该对象的对象级别锁
                food.notify();

            }
        }


    }
}

//共享资源(这里将Food设置为共享资源)
public class Food {
    public String name;
    public int price;

    //定义一个标记
    //注意false表示没有资源,true表示有资源
    public static boolean flag;

}


//测试类
public class MyTest {
    public static void main(String[] args) {
        Food food = new Food();
        SetThread setThread = new SetThread(food);
        GetThread getThread = new GetThread(food);

        setThread.start();
        getThread.start();
    }
}




sleep与wait():

  1. wait()方法一旦等待就会释放锁;slee()方法使线程处于休眠状态,线程休眠后不会释放锁
  2. wait()方法可以设置等待的时间的量,也可以不设置等待的时间量;sleep()方法必须设置等待的时间量

volatile

内存可见性:

  • 当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
  • 对于多线程,不是一种互斥关系
  • 不能保证变量状态的“原子性操作”

线程状态:

  • 新建:线程被创建出来
  • 就绪:具有CPU的执行资格,但是不具有CPU的执行权
  • 运行:具有CPU的执行资格,也具有CPU的执行权
  • 阻塞:不具有CPU的执行资格,也不具有CPU的执行权
  • 死亡:不具有CPU的执行资格,也不具有CPU的执行权

CAS算法:

CAS中有3个操作数,需要读写的内存值V,需要比较的值A,以及拟写入的新值B。当且仅当预期值A与内存值V相同时,将内存值 V修改为B,否则什么都不做,保障了原子性
java.util.concurrent.atomic 包下提供了一些原子操作的常用类:

  • AtomicBoolean 、 AtomicInteger 、 AtomicLong 、AtomicReference
  • AtomicIntegerArray 、 AtomicLongArray
  • AtomicMarkableReference
  • AtomicReferenceArray

例:

//在java.util.concurrent.atmoic包下提供了一些原子变量。
// 所谓原子变量,就是类的小工具包,支持在单个变量上解除锁的线程安全编程。
import java.util.concurrent.atomic.AtomicInteger;
public class MyRunnable implements Runnable {
       AtomicInteger i= new AtomicInteger(1);
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i.getAndIncrement());//i++
        }
    }
}

public class MyTest {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        for (int i = 0; i < 10; i++) {
            new Thread(myRunnable).start();

        }
    }
}

线程池–Executors:

创建大量生存期很短的线程时。

  • public static ExecutorService newCachedThreadPool(): 根据任务的数量来创建线程对应的线程个数
  • public static ExecutorService newFixedThreadPool(int nThreads): 固定初始化几个线程
  • public static ExecutorService newSingleThreadExecutor(): 初始化一个线程的线程池

方法:

  • Future<?> submit(Runnable task)
  • Future submit(Callable task)
 public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        //给线程池中提交任务
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + "执行了111111");
                }

            }
        });
        executorService.submit(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + "执行了111111");
                }

            }
        });
        executorService.submit(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + "执行了111111");
                }

            }
        });

        //关闭线程池
        executorService.shutdown();

    }

阿里手册:

 public static void main(String[] args) {
        //阿里的规范手册中明确:
        //线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样
        // 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
        // 说明:Executors 返回的线程池对象的弊端如下:
        // 1)FixedThreadPool 和 SingleThreadPool :
        //     允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
        // 2)CachedThreadPool 和 ScheduledThreadPool :
        //     允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
        // ExecutorService executorService = Executors.newCachedThreadPool();

     /*

        //corePoolSize表示常驻核心线程数,如果大于0,即使本地任务执行完也不会被销毁
        //
      public ThreadPoolExecutor( int corePoolSize,
        int maximumPoolSize,
        long keepAliveTime,
        TimeUnit unit,
        BlockingQueue<Runnable> workQueue,
        ThreadFactory threadFactory,
        RejectedExecutionHandler handler)}*/
    }
public static void main(String[] args) {
        /*   public ThreadPoolExecutor(
        int corePoolSize, 表示常驻核心线程数,如果大于0,即使本地任务执行完也不会被销毁
        int maximumPoolSize, 表示线程池能够容纳可同时执行的最大线程数
        long keepAliveTime, 表示线程池中线程空闲的时间,当空闲时间达到该值时,线程会被销毁,只剩下 `corePoolSize` 个线程位置
        TimeUnit unit, `keepAliveTime` 的时间单位,最终都会转换成【纳秒】,因为CPU的执行速度杠杠滴
        BlockingQueue<Runnable> workQueue, 当请求的线程数大于 `maximumPoolSize` 时,线程进入该阻塞队列
        ThreadFactory threadFactory, 顾名思义,线程工厂,用来生产一组相同任务的线程,同时也可以通过它增加前缀名,虚拟机栈分析时更清晰
        RejectedExecutionHandler handler 执行拒绝策略,当 workQueue 达到上限,同时也达到 maximumPoolSize 就要通过这个来处理,比如拒绝,丢弃等,这是一种限流的保护措施

        )}
        */

        //自己指定创建线程池
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 10, 10L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        //提交任务
        threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("任务执行完了");
            }
        });

        threadPoolExecutor.shutdown();
    }

定时器:

Timer:

  • public Timer()

  • public void schedule(TimerTask task, long delay):

  • public void schedule(TimerTask task,long delay,long period);

  • public void schedule(TimerTask task, Date time):

  • public void schedule(TimerTask task, Date firstTime, long period):

  • TimerTask:定时任务

  • public abstract void run()

  • public boolean cancel()

 public static void main(String[] args) {
        //定时器,可以在指定的时间,执行定时任务
        //一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。
        Timer timer = new Timer();
        // 类 TimerTask 由 Timer 安排为一次执行或重复执行的任务。
        //等待多少毫秒之后,来执行这个定时任务
        MyTimerTask myTimerTask = new MyTimerTask(timer);
        timer.schedule(myTimerTask, 1000 * 5);
        //取消定时任务
        //myTimerTask.cancel();
        //取消定时器:终止此计时器,丢弃所有当前已安排的任务。
        //timer.cancel();

    }
}

class MyTimerTask extends TimerTask {
    private Timer timer;
    public MyTimerTask(Timer timer) {
        this.timer = timer;
    }
    @Override
    public void run() {
        System.out.println("砰~~~爆炸了");
        //取消定时器
        //timer.cancel();
    }
 public static void main(String[] args) {
        Timer timer = new Timer();
        //第一次等待两秒执行任务,以后间隔1s不间断的执行异步任务。
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("砰~~爆炸了");
            }
        }, 1000 * 2, 1000);
    }

开发中:
Quartz是一个完全由java编写的开源调度框架。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值