适用于刚刚接触java多线程,或者面试java基础概念的浅层次学习。
主要是概念
多线程的基本概念
线程指进程中的一个执行场景,也就是执行流程,一个进程对应一个应用程序;
每个进程是一个应用程序,都有独立的内存空间;
同一个进程中的线程共享其进程中的内存和资源;
单进程计算机只能做一件事情, 多线程计算机可以同时做多个事情。
线程一个进程中执行的场景,一个进程可以有多个线程;
进程提高CPU使用率,进程提高应用程序使用率;
线程和线程共享“堆内存和方法区内存”,栈内存是独立的,一个线程一个栈。线程的创建和启动
第一种方式:继承 java.lang.Thread 类,重写run()方法;
//定义一个线程
class Processor extents Thread{
//重写run方法
public void run(){
for(int i=0;i<=20;i++){
System.out.println("run--->"+i);
}
}
}
public static void main(String [] args){
//创建线程
Thread t = new Processor();
//启动线程
/*这段代码执行瞬间结束,告诉JVM再分配一个新的栈给t线程*/
/*run不需要程序员手动调用,系统线程启动之后自动调用run方法*/
t.start();
/*如果下面这么写的话,这只是普通方法调用*/
//t.run();
for(int i=0;i<=20;i++){
System.out.println("main--->"+i);
}
}
第二种方式:实现 java.lang.Runnable 接口,实现run()方法;
class Processor implements Runnable{
public void run(){
for(int i= 0;i<=20;i++){
System.out.println("run-->"+i);
}
}
}
public static void main(String [] args){
//创建线程
Thread t = new Thread(new Processor);
//启动
t.start();
}
- 线程的生命周期
五个周期:新建、就绪、运行、阻塞、死亡。
new()-->新建
start()-->就绪
//就绪状态的线程表示有权利去获取CPU的时间片(执行权)当线程得到时间片后就执行run方法,这个时候就进入了运行状态
run()-->运行状态
线程的调度
Java使用的是抢占调度模型,所有的线程轮流使用CPU使用权,
优先级高的线程获取的CPU时间片的时间线程的优先级:
1、MAX_PRORITY(最高级)10
2、MIN_PRORITY(最低级)1
3、NORM_PRORITY(标准)默认5
- 线程的控制
Thread.sleep(毫秒);
*这是个静态方法;
*阻塞当前线程, 让出CPU给其他线程执行;
*Thread中run方法不抛出异常,重写run方法后不能使用throws。只能使用try catch(InterruptedException)
*线程正在休眠,可以使用Interrupt();触发异常处理机制,终止休眠。
如何正确的终止一个正在执行的线程?通过线程执行状态、通过其他线程
Thread.yield();
*这是个静态方法;
*让同优先级的线程有执行的机会,让位时间不固定;
Thread.join();
*线程的合并
*出现在哪个线程则与该线程合并(两个栈合并)
- 线程的同步
1.为了数据的安全,不得不放弃效率,变成了(等同)单线程;
2.使用线程同步的三个因素:
(1)多线程环境;
(2)多线程共享同一数据;
(3)共享数据涉及到了修改操作;
3.synchronize(共享对象 例:this){ 操作、修改功能}
4.如果关键字添加到成员方法上,线程拿走的也是当前的对象锁;
–多线程下线程安全的方法:
StringBuffer();
Vector();
Hashtable();
他们的源码中方法都有synchronize关键字修饰。
类锁,类只有一个
synchronize 添加到静态方法上,
线程执行此方法时候会找类锁
@死锁code例:
public class ThreadTest {
public static void main(String[] args) {
Object o1 = new Object();
Object o2 = new Object();
Thread t1 = new Thread(new T1(o1,o2));
Thread t2 = new Thread(new T2(o1,o2));
t1.start();
t2.start();
}
}
class T1 implements Runnable{
Object o1;
Object o2;
public void run() {
synchronized (o1) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) { }
synchronized (o2) { }
}
}
T1(Object o1,Object o2){
this.o1=o1;
this.o2=o2;
}
}
class T2 implements Runnable{
Object o1;
Object o2;
public void run() {
synchronized (o2) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) { }
synchronized (o1) { }
}
}
T2(Object o1,Object o2){
this.o1=o1;
this.o2=o2;
}
}
守护线程的概念
守护线程:用户线程;
所有的用户线程结束,守护线程退出;
守护线程一般都是无限执行的;
- 定时器的使用
@每隔一段时间定时执行一段代码
t.schedule(TimerTask task,Date firstTime,long period)
//例:
Timer t = new Timer();
t.schedule(
new LogTimerTask(),
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS")
.parse("2018-03-08 21:21:21 000"),
1000*10);
class LogTimerTask extends TimerTask{
public void run(){
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").fomat(new Date()));
}
}