动力节点首页 全国咨询热线:400-8080-105

绑定手机号,登录
手机号

验证码

微信登录
手机号登录
手机号

验证码

30天自动登录
微信登录与注册
微信扫码登录与注册

扫码关注微信公众号完成登录与注册
手机号登录
首页 > 文章

Java多线程基础

03-31 22:39 331浏览
举报 T字号
  • 大字
  • 中字
  • 小字

一、进程与线程

进程:程序运行资源分配的最小单位,进程内部有多个线程,会共享这个进程的资源

线程:CPU调度的最小单位,必须依赖进程而存在。

二、并行和并发

并行:同一时刻,可以同时处理事情的能力

并发:与单位时间相关,在单位时间内可以处理事情的能力

三、线程实现方式

1.继承Thread类

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("继承Thread类创建线程");
    }

    public static void main(String[] args) {
        Thread myThread=new MyThread();
        myThread.start();
    }
}

2.实现Runnable接口

public class MyThread implements Runnable {
    @Override
    public void run() {
        System.out.println("实现Runnable接口创建线程");
    }

    public static void main(String[] args) {
        Thread thread=new Thread(new MyThread());
        thread.start();
    }
}

3.实现Callable接口

public class MyThread implements Callable {
    @Override
    public Object call() throws Exception {//有返回值
        System.out.println("实现Callable接口创建线程");
        return "result";
    }

    public static void main(String[] args) throws Exception{
        FutureTask futureTask=new FutureTask(new MyThread());
        Thread thread=new Thread(futureTask);
        thread.start();
        System.out.println(futureTask.get());
    }
}

4.线程池

public static void main(String[] args) throws Exception{
        ExecutorService executor= Executors.newCachedThreadPool();
        executor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("通过线程池创建线程");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    executor.shutdown();
                }
            }
        });
}

注:Runnable与接口Callable区别

Callable规定的方法是call(),Runnable规定的方法是run()

Callable的任务执行后可返回值,而Runnable的任务是不能返回值得

四、终止线程

stop () 已废弃,因为stop ()会导致线程不会正确释放资源

resume () 继续 和 suspend ()挂起 已废弃,suspend ()容易导致死锁

interrupt() 和 isInterrupted() 调用一个线程的interrupt() 方法中断一个线程,并不是强行关闭这个线程,只是跟这个线程打个招呼,将线程的中断标志位置为true,线程是否中断,由线程本身决定。isInterrupted() 判定当前线程是否处于中断状态。java线程是协作式,而非抢占式

interrupted() 是static方法,判定当前线程是否处于中断状态,同时中断标志位改为false。

注:方法里如果抛出InterruptedException,线程的中断标志位会被复位成false,如果确实是需要中断线程,要求我们自己在catch语句块里再次调用interrupt()。

五、线程生命周期

新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5种状态。

线程只有5种状态。整个生命周期就是这几种状态的切换。

六、run()和start()

run方法就是普通对象的普通方法

只有调用了start()后,Java才会将线程对象和操作系统中实际的线程进行映射,再来执行run方法。

七、线程的优先级

取值为1~10,缺省为5,但线程的优先级不可靠,不建议作为线程开发时候的手段

八、守护线程(DaemonThread)

守护线程与普通线程的唯一区别是:当JVM中所有的线程都是守护线程的时候,JVM就可以退出了;如果还有一个或以上的非守护线程则不会退出。

守护线程中finally不能保证一定执行

九、synchronized内置锁

对象锁,锁的是类的对象实例 。多次new实例对象,分别调用加锁的方法是并行的,只有是同一个对象多次调用加锁方法才会存在竞争,spring缺省是单例的,对象是唯一的。

类锁 ,锁的是每个类的的Class对象,每个类的的Class对象在一个虚拟机中只有一个,所以类锁也只有一个。

十、volatile

volatile变量的读写对所有线程立即可见只是读和写一步,复杂的运算不能保证对其他线程可见,因为复杂的运算可能会被编译成多条指令,JMM只保证,volatile变量从工作内存写回到主内存是对其他线程可见的。

谈到volatile,理解原子性和易变性是不同的概念这一点很重要,volatile是轻量级的锁,它只具备可见性,但没有原子特性。如果你将一个域声明为volatile,那么只要对这个域产生了写操作,所有的读操作都可以看到这个修改,即便使用了本地缓存也一样,volatile会被立即写入到主内存中,而读的操作就发生在主内存中。在非volatile域上的原子操作不必刷新到主内存中,所以读操作的任务看不到这个值,如果多个任务在同时访问某个域,那么这个域就应该是volatile,否则这个域就应该经过同步来访问,同步也会导致向主内存中刷新。使用volatile而不是synchronized的唯一安全的情况就是类中只有一个可变的域。个人认为,第一选择应该是synchronized,这应该最安全的方式如果并发水平不高,最好还是不要使用。

0人推荐
共同学习,写下你的评论
0条评论
代码小兵959
程序员代码小兵959

5篇文章贡献15809字

相关课程 更多>

作者相关文章更多>

推荐相关文章更多>

Java面试题及答案整理

代码小兵66904-21 20:01

6道经典算法面试题

杨晶珍05-12 16:39

简述Spring MVC的核心组件

代码小兵49806-11 16:26

SpringMVC 中的组件

代码小兵49806-11 16:28

Spring常见面试题

代码小兵92504-17 16:07

发评论

举报

0/150

取消