JAVASE

           第九章 多线程

本章学习内容

  1. 多线程概述
  2. 开启线程两种方式
  3. 线程常用方法
  4. 线程池
  5. 定时器

多线程引入
程序有一条执行流程,叫单线程程序
程序有多条执行流程,叫 多线程程序
多线程的概述:
进程:
1、正在运行的程序,由系统进行资源的方配合调用独立的单位
2、每个进程都有自己的内存空间和资源
线程
1、是进程中的单个顺序控制流,是一条执行路径
2、一个进程有一条执行路径,为单线程程序。
3、一个进程有多条执行路径,为多线程程序。
4、线程是程序中单个顺序的控,是程序使用CPU的基本单位
Java启动压原理
java 命令会启动 java 虚拟机,启动 JVM,等于启动了一个应用程序,也就是启动了一个进程。该进程会自动启动一个 “主线程” ,然后主线程去调用某个类的 main 方法。所以 main方法运行在主线程中。在此之前的所有程序都是单线程的

强调内容
线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。
为什么要重写run()方法:因为子线程创建成功之后会去调run方法,我们要交给子线程做的事情就应该放在run方法中
启动线程使用的是那个方法:start方法
线程能不能多次启动:不行
run()和start()方法的区别:
调用start方法向JVM发出命令,JVM会首先创建一个子线程,然后子线程内部再通过当前对象引用去调用run方法,run方法就是在子线程中执行
多线程的方案一

1、 用API来实现,参考Thread
2、继承Thread类
为什么要重写run()方法
启动线程使用的是那个方法
线程能不能多次启动
run()和start()方法的区别

怎样获取设置名称
public final String getName()
public final void setName(String name)
其实通过构造方法也可以给线程起名字
思考:如何获取main方法所在的线程名称呢
1. 一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法
代码如下:
public class ThreadDemo2 {
public static void main(String[] args) {
MyThread2 t = new MyThread2(“子线程”);
// public final String getName()返回该线程的名称。
String threadName = t.getName();
System.out.println(threadName);// 子线程
// public final void setName(String name)改变线程名称,使之与参数 name 相同。
t.setName(“子线程test”);
t.start();

    // public static Thread currentThread()返回对当前正在执行的线程对象的引用。
    Thread currentThread = Thread.currentThread();
    String mainThread = currentThread.getName();
    System.out.println(mainThread);// main
    currentThread.setName("主线程");
    System.out.println(currentThread.getName() + "---over");
}

}

class MyThread2 extends Thread {
public MyThread2(){

}

public MyThread2(String name) {
    super(name);//调用父类的有参构造方法,重命名线程名称
}

@Override
public void run() {
    for (int i = 0; i < 10; i++) {
        System.out.println(getName() + "---" + i);
    }
}

方案二
1、实现Runnable接口
如何获取线程名称
如何给线程设置名称
2、实现接口方式的好处
可以避免由于Java单继承带来的局限性。
适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效分离,较好的体现了面向对象的设计思想。
安全原因
线程同步安全问题出现的原因:
操作共享数据ticket的代码不是原子性的,是可以分割的,而且是多线程环境下
判断一个程序是否存在线程安全问题的依据:
是否是多线程环境
是否存在共享数据
是否存在多条语句操作共享数据
基本思想:让程序没有安全问题的环境。
怎么实现呢?
把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可。

锁对象:多个线程要保证使用的是同一个锁对象,或者你保证锁对象是唯一的
同步代码块概述:就是把某一段存在线程安全问题的代码给锁起来
    格式:synchronized(锁对象){
            存在线程安全问题的代码;
        }
同步方法概述:就是把整个方法都上锁,认为整个方法都存在线程同步安全问题
    格式:修饰符 synchronized 返回值类型 方法名(参数列表){
    }
非静态同步方法的锁对象:this
静态同步方法的锁对象:当前的字节码文件对象

虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,
为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock
Lock
    void lock()上锁
    void unlock()释放锁

wait,notify,notifyAll不能通过Lock对象来调用

解决线程安全问题有几种方法?
    同步方法:效率第三
    同步代码块:效率第二
    Lock锁:效率第一

线程安全问题的思想
1、是否出现什么问题
a、是否出现多线环境问题
b、是否共享数据
c、多条语句是否共享
2、怎样解决多线程安全问题;
把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可。
解决方法一
同步代码块格式:
synchronized(锁对象){
需要同步的代码;
}
同步可以解决安全问题的根本原因就在那个锁对象上。该锁对象如同锁的功能。
解决方法二
1、同步方法就是把同步关键字加到方法上
2、同步方法的锁对象是什么呢?
3、如果是静态方法,同步方法的锁对象又是什么呢?
lock的使用
1、虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock
2、Lock
void lock()上锁
void unlock()释放锁
ReentrantLock
死锁
1、效率低
2.出现同步嵌套,就容易死锁
匿名内部类方式使用多线程
1、匿名内部类方式使用多线程
2、new Thread(){代码…}.start();
3、New Thread(new Runnable(){代码…}).start()
线程池
1、线程池概述:创建线程是需要消耗系统资源的,如果用完一个线程之后就让其释放,下一次再使用线程需要再次创建,效率比较低,也比较消耗系统资源。
这时候可以创建一个线程池,把用完的线程放到这个池子里面去,如果其它地方需要使用线程可以直接从这个池子里面取就可以了。
2、 线程池如何实现呢?
JDK1.5之后就内置了,使用Executors的静态方法就可以获取线程池,当然你也可以通过ThreadPoolExecutor这个类自定义线程池。
3、JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
public static ExecutorService newCachedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads)
public static ExecutorService newSingleThreadExecutor()
这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程。它提供了如下方法
void execute(Runnable command)
定时器
1、定时器是一个应用十分广泛的线程工具,可用于调度多个定时任务以后台线程的方式执行。在Java中,可以通过Timer和TimerTask类来实现定义调度的功能
2、Timer
public Timer()
public void schedule(TimerTask task, long delay)
public void schedule(TimerTask task,long delay,long period)
public void cancel()
3、TimerTask
public abstract void run()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值