2.Java 并行程序基础

Wesley13
• 阅读 772

1.初始线程:线程的基本操作

1.新建线程

2.终止线程

  • stop

造成数据不一致

3.线程中断

public void Thread.interrupt()              // 中断线程
public boolean Thread.isTnterrupted()        // 判断是否被中断
public static boolean Thread.interrupted()  // 判断是否被中断,并清除当前中断状态

4.等待(wait)和通知(notify)

public final void wait() throws InterruptedException
public final native void notify()
//
public static native void sleep(long millis) throws InterruptedException

Object.wait()和Thread.sleep()方法都可以让线程等待若干时间。除了wait()可以被唤醒外,另外一个主要区别就是wait()方法会释放目标对象的锁,而Thread.sleep()方法不会释放任何资源。

Object.wait()方法并不是可以随便调用的。它必须包含在对应的synchronzied语句中,无论是wait()或者notify()都需要首先获得目标对象的一个监视器。

5.挂起(suspend)和继续执行(resume)线程

suspend() 在导致线程暂停的同时,并不会取释放任何锁资源。

6.等待线程结束(join)和谦让(yield)

join

public final void join() throws InterruptedException
public final synchronized void join(long millis) throws InterruptedException

join:一个线程的输入可能非常依赖另外一个或者多个线程的输出,此时这个线程就需要等待依赖线程执行完毕,才能继续执行。

  • join():无限等待,它会一致阻塞当前线程,直到目标线程执行完毕。
  • join(long millis):给出一个最大等待时间,如果超过给定时间目标线程还在执行,当前线程也会因为“等不及了”,而继续往下执行。

join() 的本质是让调用线程 ==**wait()**== 在当前线程对象实例上

//核心代码
while (isAlive()) {
   wait(0);
}

它让调用线程在当前线程对象上进行等待。当线程执行完成后,被等待的线程会在退出前调用notifyAll() 通知所有的等待线程继续执行。因此,值得注意的一点是:不要在应用程序中,在Thread对象实例上使用类似wait()或者notify()等方法,因此这很有可能会影响系统API的工作,或者被系统API所影响

yield

public static native void yield();

2. volatile与Java内存模型(JMM)

volatile:使用volatile申明一个变量时,就等于告诉虚拟机,这个变量极有可能会被某些程序或者线程修改。为了确保这个变量被修改后,应用程序范围内的所有线程都能够“看到”这个改动,虚拟机就必须采用一些特殊的手段,保证这个变量的可见性等特点。

注意:volatile并不能代替锁🔒,它也无法保证一些符合操作的原子性。 例如:👇

public class VolatileTest {

    volatile static int i = 0;

    public static class PlusTask implements Runnable{
        public void run(){
            for(int k = 0;k<10000;k++){
                i++;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[10];
        for (int i = 0;i<10;i++){
            threads[i] = new Thread(new PlusTask());
            threads[i].start();
        }

        for (int i = 0;i<10;i++){
            threads[i].join();
        }
        System.out.println(i);
    }
}

volatile 也能保证数据的可见性和有序性

3.分门别类的管理:线程组

// 创建线程组
ThreadGroup tg = new ThreadGroup("PrintGroup");
// 使用Thread构造方法指定线程所属的县城组
Thread t = new Thread(tg,new ThreadTest(),"T1");

stop:慎用,它会停止线程组中所有的线程。和Thread.stop()一样。

4.驻守后台:守护线程(Daemon)

比如:垃圾回收线程、JIT线程

与之对应的是用户线程,当一个Java内,只有守护线程时,Java虚拟机就会自然退出。

public class DaemonDemo {
    public static class DaemonT extends Thread{
        public void run(){
            while(true){
                System.out.println("I'm alive");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t = new DaemonT();
        t.start();
        // 将t设置为守护线程
        t.setDaemon(true);
        Thread.sleep(3000);

    }
}

5.先干重要的事:线程优先级

使用1-10表示线程优先级。一般使用内置的三个静态标量表示:
数字越大则优先级越高。

/**
 * The minimum priority that a thread can have.
 */
public final static int MIN_PRIORITY = 1;

/**
 * The default priority that is assigned to a thread.
 */
public final static int NORM_PRIORITY = 5;

/**
 * The maximum priority that a thread can have.
 */
public final static int MAX_PRIORITY = 10;

6.线程安全的概念与synchronized

synchronized:是实现线程间的同步。它的工作是对同步的代码加锁,使得每一次,只能有一个线程进入同步块,从而保证线程间的安全性。

用法:

  • 指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。
  • 直接作用于实例方法:相当于对当前实例加锁,进入同步前要获得当前实例的锁
  • 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。

7.程序中的幽灵:隐蔽的错误

ArrayList 线程不安全 HashMap 线程不安全. ConcurrentHashMap代替

8.初学者常见问题:错误的加锁


参考文献: 《Java高并发设计》

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
御弟哥哥 御弟哥哥
3年前
如何正确停止Java线程,终止Java线程的三种方法
如何正确停止Java线程,终止Java线程的三种方法在Java中有以下3种方法可以终止正在运行的线程:1.使用退出标志,使线程正常退出,也就是当run()方法完成后线程终止。2.使用stop()方法强行终止线程,但不推荐,该方法已被弃用,原因见后文。3.使用interrupt方法中断线程。以下内容翻译自J
Wesley13 Wesley13
3年前
4、jstack查看线程栈信息
1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
03.Android崩溃Crash库之ExceptionHandler分析
目录总结00.异常处理几个常用api01.UncaughtExceptionHandler02.Java线程处理异常分析03.Android中线程处理异常分析04.为何使用setDefaultUncaughtExceptionHandler前沿上一篇整体介绍了crash崩溃
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Wesley13 Wesley13
3年前
Java多线程:线程属性
\线程属性id:线程唯一标识。自动生成。不允许修改。name:线程的名字,可以自定义成有具体含义的名字,便于识别不同作用的线程。(可同名)isDaemon:是否是守护线程。true守护线程,false用
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这