多线程
来源:互联网 发布:excel数据透视表命名 编辑:程序博客网 时间:2024/06/06 02:14
多线程
多线程:程序的执行路径有多条
单线程:程序的执行路径只有一条.
面试题:Jvm,java虚拟机是多线程程序吗?
答:是多线程程序,由于java虚拟机中自带一个垃圾回收器,来确保程序不会轻易的造成内存溢出!
至少开启两条子线程:
1)当前程序在执行代码的时候,会开启main:主线程.
2)垃圾回收器会开启一个垃圾回收线程,来确保程序不会内存异常,将没用的变量或者没有更多引用的对象来回收掉.
如何实现多线程程序?
1)要实现多线程程序,必须创建一个进程.
2)创建进程需要调用系统资源进行创建,但是Java语言不能直接调用系统资源.
3)C/C++语言可以创建系统资源,然后使用Java语言调用C/C++已经封装好的东西.
4)Java---->类:Thread类.
并发和并行:
并发:指的是同一个时间点.
并行:指的是同一个时间段.
多线程程序的实现方式1:
1)自定义一个类:MyThread继承自Thread类
2)在MyThread类中重写Thread类中的run()方法.
3)在主线程中,创建该类的实例对象,启动线程--- >调用start()方法.
为什么重写run()方法: run方法里面执行的耗时的操作:线程睡眠,线程等待,循环语句等.
如何获取线程的名称:
publicfinal String getName() 返回线程的名称.
设置线程名称:
publicfinal void setName(String name) 改变线程名称,使之与参数name相同
public final int getPriority() 返回线程的优先级
默认优先级:5
Java.lang.Thread:
publicstatic final int MAX_PRIORITY 10 :最大优先级
publicstatic final int MIN_PRIORITY 1 :最小优先级
publicstatic final int NORM_PRIORITY 5 :默认优先级
优先级大的抢占到CPU的执行权大,但并不代表一定能抢到,因为线程的执行具有随机性.
给线程设置优先级:setPriority();
public static void yield() 暂停当前正在执行的线程对象,并执行其他线程
暂停当前线程执行其他线程,并不保证另一个线程就一定能抢占到CPU的执行权.
public final void join()
throwInterruptedException 等待该线程终止(必须先启动线程)
线程睡眠:
publicstatic void sleep(long millis)
ThrowsInterruptedException 在指定的毫秒数内让正在执行的线程休眠(暂停执行)
线程停止:
publicfinal void stop() : 强迫线程停止执行
publicvoid interrupt() 中断线程, 表示中断线程一种状态
public final void setDaemon(boolean on) on指定true,就是设置守护线程.
将该线程标记为守护线程或者用户线程,当正在运行的线程都是守护线程时,java虚拟机退出.
该方法必须在启动线程前调用.
Jvm自动退出,对于主线程的数据如果直接输出完毕,对于两个守护线程不会立即消失,jvm等会就自动退出.
多线程实现的第二种方式:(实际开发中第二种比第一种应用更为广泛)
开发步骤:
1) 自定义一个类MyRunnable,该类实现Runnable接口
2) 实现该接口中的run()方法.
3) 在主线程中创建该类的实例对象
4) 创建Thread类对象,将3)创建的对象作为参数进行传递
5) 分别启动线程
第二种方式优于第一种方式,采用Java设计原则:数据分离原则,而第一种单继承具有局限性.
面试题:多线程的实现方式有几种,分别是什么?
答:三种方式
1)继承Thread类2)实现Runnable接口3)实现Callable接口
继承Thread类:
1)自定义一个类:MyThread继承自Thread类
2)在MyThread类中重写Thread类中的run()方法.
3)在主线程中,创建该类的实例对象,启动线程--- >调用start()方法.
实现Runnable接口:
1) 自定义一个类MyRunnable,该类实现Runnable接口
2) 实现该接口中的run()方法.
3) 在主线程中创建该类的实例对象
4) 创建Thread类对象,将3)创建的对象作为参数进行传递
5) 分别启动线程
实现Callable接口: 线程池利用Executors工厂类来进行ExecutorService对象的创建(线程池指定当前线程池中有多个线程)
利用submit(Runnabletarget) 提交异步任务
submit(Callable target) 提交异步任务
实现接口中的call():
结束线程池shutdown();
如何解决多线程的安全问题:
检验多线程安全问题的标准(判断一个多线程程序是否存在安全问题)
1)当前是否是一个多线程环境
2)多线程环境是否有共享数据
3)是否有多条语句对共享数据进行操作
将多条语句对共享数据进行操作的代码用代码块包起来
Java的同步机制:
使用同步代码块:synchronized(同步锁对象){
多条语句对共享数据的操作;
}
同步锁对象:应该每一个线程都要使用这个锁对象(同步锁):可以理解为门的开和关
使用同步代码块可以解决线程安全问题.
同步锁对象可以是什么样的对象
可以是Object类型,任意的java类
同步锁对象:
1)可以Object类型以及任意java类型对象
2)如果一个方法进来之后是一个同步代码块,那么同步代码块可以演变成一个同步方法
3)如果是一个静态的同步方法,锁对象是当前类名class属性:类名.class(反射机制:获取一些类的字节码文件对象Class类对象).
面试题:
wait()线程等待,notify()唤醒单个线程,notifyAll()唤醒所有线程,这三个方法为什么不定义到Thread类中实现呢?而是定义在Object类中?
线程中会存在安全问题,并且解决线程安全问题使用的同步代码块或者同步方法来解决,同步代码块来解决线程安全问题,就存在同步锁对象,谁能代表同步锁对象(Object以及任意的Java类),把它定义到Object类中;
线程安全的类有哪些?
Vector
StringBuffer
Hashtable
Lock锁
Lock是一个接口,它使用的是ReentrantLock子实现类
Public void lock() 获取锁.
Public void unlock() 试图释放此锁.
使用同步机制可以解决多线程的安全问题,但是自身也会有弊端
1)同步: 执行效率低,(每一个线程在抢占到CPU的执行权,就回去将门关闭,别的线程进不来)
2)容易出现死锁现象
死锁现象:两个或两个以上的线程出现互相等待的情况,就会出现死锁.
等待唤醒机制(生产者线程和消费者线程)
机制:
生产者线程生产数据,如果本身就有数据,需要等待消费者线程输出数据,利用锁对象中的notify()唤醒(通知)消费者线程来输出数据
消费者线程输出数据,那么如果本身没有数据了,需要等待生产者线程产生数据,通知生产者线程生产数据.
反射机制:利用几个方法:
Object类中的getClass()
Class类里面的forName(String className) ;类的全路径名称
类的class属性
获取当前类的字节码文件对象/Class类对象..
线程组表示一个线程的集合:Java允许一个线程中有多个线程
如何获取线程组名称:
publicfinal ThreadGroup getThreadGroup() 返回该线程所属的线程组
ThreadGrouptg1 = t1.getThreadGroup();
publicfinal String getName() 返回此线程组的名称
Stringname1 = tg1.getName();
子线程默认的线程组名称:main线程
所有的线程它的默认线程组名称就是main.
如何设置线程组名称:
publicThreadGroup(String name) 构造一个新的线程组
ThreadGrouptg = new ThreadGroup(“新的线程组名称”)
创建线程类对象,并且将线程组对象作为参数进行传递,就使用Thread类的构造方法:
publicThread(ThreadGroup group, Runnable target , String name)
Thread t1 = newThread (tg , my , ”线程1”);
JDk5新增了一个Executors工厂类来产生线程池,有以下方法:
publicstatic ExecutorService newFixedThreadPool(int nThreads)
Executors工厂类中的这个方法参数直接指定在当前线程池中有多少个线程
这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程。它提供了如下方法
ExecutorsService:接口中的方法
Future<?>submit(Runnable task)
<T>Future<T> submit(Callable<T> task)
线程池的好处:节约成本,
很多子线程调用完毕不会立即被回收掉,而是会回到线程池中被多次利用!
多线程程序的实现方式3: (很少用到)
ExecuterService:接口中的方法
<T>Future<T> submit(Callable<T> task)
该返回值表示:异步计算的结果!
//创建线程池对象,利用工厂类
ExecutorServiceThreadpool = Executors.newFixedThreadPool(2) ;
//提交Callable任务(异步任务)
Threadpool.submit(newMyCallable()) ;//相当于线程中的start()方法
Threadpool.submit(newMyCallable()) ;
//结束线程池
Threadpool.shutdown();
JavaSe中的定时器:
Timer:
常用的几个方法:
public voidschedule(TimerTask task,Date time)安排在指定的时间执行指定的任务
public voidschedule(TimerTask task, long delay)在多少毫秒后执行指定任务
public voidschedule(TimerTask task, long delay, long period)
在多少毫秒后,执行任务,并且每个多少毫秒重复执行
public void cancel()终止此计时器,丢弃所有当前已安排的任务
多线程中匿名内部类的方式
格式:
new 类名(具体类,抽象类),接口(){
重写/实现方法;
}
匿名内部类的本质:
继承了该类或者是实现该接口的子类对象!
多线线程的匿名内部类的方式
继承
new Thread(){
public void run(){
////
}
}.start();
接口的方式(这种方式多与继承方式)
new Thread(new Runnable()){
public void run(){
///
}
}.start() ;
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- Dateutil
- 查找有序二维数组中是否包含特定值
- 关于Android studio3.0的坑之butterknife 8.4.0
- LruCache缓存类源码解析
- HTTP和https的区别
- 多线程
- sql 行转列、分组、排序,
- crontab 每10秒执行一次
- matlab对图像进行重命名
- 按之字形顺序打印二叉树
- FPGA浮点小数与定点小数的换算及应用
- 关于线程(Thread)的几个问题
- svn添加新资源库报验证位置时发生错误
- Mac系统清理工具 cleanmymac双十二来袭