多线程基础(一)

一、进程与线程
进程:程序运行资源分配的最小单位,进程内部有多个线程,会共享这个进程的资源
线程: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();
    }
}
  1. 实现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();
    }
}
  1. 实现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());
    }
}

  1. 线程池
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,这应该最安全的方式如果并发水平不高,最好还是不要使用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值