Warning: file_get_contents(http://api.gonowtt.com/jj.txt): Failed to open stream: Connection timed out in /www/wwwroot/106.12.87.161/wp-includes/class-wpdb.php on line 4152
Java技术–并发 – 磊宝de小屋
Java技术–并发

线程的创建方式:

  • 继承Thread类:
    • 最直接的方式,重写Thread类的run()方法
      • run()方法中不定义任何逻辑,需要重写来进行定义具体的业务逻辑
    • 实例化该类后,通过start()启动线程【start()方法内部会自动执行run()方法】
    • 缺点:会导致不能继承其他的类,限制性较大。
class MyThread extends Thread{
    @Override
    public void run(){
    具体逻辑.........
    }
}
public static void main(){
   MyThread myThread = new MyThread();
   myThread.start();
}
  • 实现Runnable接口:
    • 大体与Thread类的功能差不多,但是是通过接口实现的方式。
class MyThread implements Runnable{
    @Overrid
    public void run(){
      具体逻辑......
    }
}

public static void main(){
  Thread t=new Thread(new MyRunnable);
  t.start();
}
  • 实现Callable接口
    • 可以有返回值,并且可以多线程处理一份资源
class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        // 线程执行的代码, 这里返回一个整型结果
        return 1;
    }
}

public static void main(String[] args) {
    MyCallable task = new MyCallable();
    FutureTask<Integer> futureTask = new FutureTask<>(task);//将callable类包装进FutureTask
    Thread t = new Thread(futureTask);
    t.start();

    try {
        Integer result = futureTask.get();  // 获取线程执行结果
        System.out.println("Result: " + result);
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}
  • 使用线程池(Excutors):
    • 一种规范管理多线程的方式,避免了线程创建和销毁的开销
Class Task implement Runnable{
  @Override
  public void run(){
  具体逻辑.............
  }
}
public static void main(){
 ExecutorService executor= new Executors.newFixedThreadPool(10)//设置线程池大小:10
for(int i;i<10;i++){
 executor.submit(new Task());
   }
 executor.shutdown;
 }

如何终止线程:

  • 使用sleep()休眠线程,然后调用interrupt方法使线程标记为中断状态,在线程提交完此次任务后自我了断
  • 使用stop()暴力停止:但是会有很大不好的后果,已被废弃
  • 使用interrupt方法标记为中断状态,在run方法中判断线程状态,如果是中断则return或手动抛出异常

线程的状态:

  • New:刚刚被创建,还未start(),初始状态
  • Runnable:调用了start(),正在运行状态
  • Blocked:正在等待阻塞状态
  • Waitting:正在等待其他线程完成指定动作,等待状态
  • Timed_waitting:人为设置了等待时间的等待状态W
  • Terminated:线程完成任务,终止状态

Sleep和Wait的区别:

  • 锁处理:Sleep不释放锁,抱着锁睡觉(但会释放CPU)。而wait方法会释放锁
  • 使用位置:sleep可以在任何位置使用,而wait必须在synchronzed代码块/方法中使用
  • 唤醒条件:sleep睡醒后就苏醒,而wait必须要等待notify()来唤醒
  • 用途:sleep用于暂停线程,而wait用于线程间的通信与协作
  • Wait和Blocked的区别:
    • Wait是主动暂停,用于与其他线程的写作。而Blocked是抢锁失败,进入阻塞
    • Wait需要显式的唤醒,而Blocked会主动去抢锁

线程间的通信方式:

  • wait()、notify()、notifyAll():
    • 最基础的通信方式
  • Lock()和Condition接口:
    • 提供了一种比synchronzed更轻量灵活的锁机制
  • volatile关键字:
    • 用volatile关键字修饰的变量再被更改后会立即通知其他线程,保证变量的可见性
  • Semaphore信号量:一个计数的信号量,可以控制特定资源的访问

优雅的停止线程的方式

不应该暴力的停止(如stop)。而是应该通过逻辑控制停止

  • 通过共享标志变量来控制:
    • 用volatile关键字修饰一个变量,当工作线程检测到为false时停止(设置中断标志)
  • 直接使用线程中断机制:
    • 通过Tread.interrupt()来标识中断标志,当线程执行完当前任务则会自动中断。

如何保证线程安全:

  • synchronized关键字:同步代码块或方法,确保同一时间只能有一个线程进入代码块
  • volatile关键字:作用于变量,确保所有线程都能及时看到该变量的值
  • 使用ReentrantLock可重入锁:实现Lock接口。比synchronized更加强大的锁机制,就是那种需要fianlly解锁的那种
  • 使用JUC提供的原子类:如AtomicInterger
  • 使用并发安全的集合:如ConcurrentHashMapper;CopyOnWriteArryayList;ConcurrentLinkedQueue等

Java中常用的锁:

  • Synchronized内置锁:
    • 是一种可重入锁,公平锁
    • 当没有其他线程竞争时,会使用无锁、偏向锁、轻量级锁、重量级锁
  • ReentrantLock可重入锁:
    • 默认非公平锁
    • 比起Synchronized更加灵活功能高级,如定时锁等待,是否公平
  • ReadWriteLock读写锁:
    • 允许多个读取者但是只允许一个写入者,用于读远多于写的情况
  • 自旋锁(思想):线程在等待锁时会持续循环检查锁是否可用,通常用于锁等待时间很短的情况,通常用CAS替代
  • 锁的公平性:
    • 公平:按先后顺序来
    • 不公平:按线程获取锁的CAS来

synchronized的四种量级

  • 无锁:没有任何线程持有锁
  • 偏向锁:在锁内部维护一个线程ID,如果该线程再次获取锁则直接进入。当有线程竞争锁时升级为轻量级锁
  • 轻量级锁:当线程轻微竞争时,其他线程需要自旋来等待锁的释放,自旋不断尝试获取锁,占用CPU
    • 后期Java废弃了偏向锁,因为现代应用持续的并发都比较高,偏向锁的撤销反而浪费性能
  • 重量级锁:当线程激烈竞争时,其他线程获取不到锁会直接进入阻塞状态。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇