【掌握的】
1.两种方式创建线程:(继承,实现)
2.继承和实现的区分
3.线程的生命周期
4.不同状态下,所对应的方法。【通过哪些方法,可以让线程达到某个状态。】
5.同步代码块,同步方法。
----------------------
1.学习多线程的原因?
生活中:
程序: 一个完整的功能代码。(方法,没有被运行)
进程: 一个完整的功能代码。(方法,被运行)
线程: 进程包含线程。
好处:提高代码的执行效率。总是有一些功能是需要同时执行的,那就需要多线程。
2.主线程:
-----执行main方法里的代码。
普通线程
------run 方法里的代码。
3.完成线程的步骤:
A. 编写线程类:(1.通过继承)
B. 重写run方法:
C. 创建线程对象,调用start方法,开启线程。
补充:
(1) 线程对象.run(); 没有开启线程,只是在调用线程对象的run()方法。
线程对象.start(); 线程开启的标志,自动调用run()方法
(2) 调用start()方法就立刻执行run()方法吗?
线程对象.start(); ----当前线程所处的状态是“就绪状态”
真正执行run();----当前线程所处的状态是“运行状态”
----“就绪状态” 和“运行状态” 之间,间隔多久,不清楚。
(3)线程 【默认命】和【指定名】。
普通线程的默认名:Thread-变量 ----变量static的,从0开始计数
主线程默认名:main
// private String name; //1.接收外界传入的参数,完成线程名。
// public Thread1(String name){
// this.name=name;
// }
public Thread1(String name){//2.调用父类有参,完成线程命名。
super(name);
}
public void run() {
// Thread.currentThread().setName(name);
for (int i = 1; i <= 10; i++) {
System.out.println
(Thread.currentThread().getName()+"--->"+i);
}
}
【2.通过实现完成线程】
A.编写线程类:
B.。重写run()方法
C。创建线程实现类对象,
创建线程对象,
线程对象调用方法,开启线程。
补充: (1.) Thread 实现 Runnable接口
(2.)Thread th
Thread2 th2
都实现Runnable接口 ,在th .start();---th2.run()被执行。【代理模式】
(3.)继承方式, VS 实现方式 哪种线程类更好?
实现方式 好:
1.可以多实现
2.数据共享。
【例子:3个窗口同时销售5张火车票】
【继承方式:】
public class ThreadPiao extends Thread {
private int piao=5;
public void run() {
for(int i=1;i<=100;i++){
if(piao>0){
System.out.println
(Thread.currentThread().getName()+"---"+piao--);
}
}
}
}
【测试代码】
new ThreadPiao().start();
new ThreadPiao().start();
new ThreadPiao().start();
【实现方式】
public class ThreadP implements Runnable {
private int piao=5;
public void run() {
for(int i=1;i<=100;i++){
if(piao>0){
System.out.println
(Thread.currentThread().getName()+"---"+piao--);
}
}
}
}
【测试代码】
ThreadP tp=new ThreadP();
new Thread(tp).start();
new Thread(tp).start();
new Thread(tp).start();
问题:继承方式,可不可以只new 1个线程对象,然后调用3次start()方法?
4.线程状态/生命周期:
A.新生状态: new 线程类();
B.就绪状态: start(); 【有被执行的资格,但是还没有被cpu调度;队列】
C.运行状态: run();
D.阻塞状态: sleep(): 礼让 yi (); 强制 join();
D.死亡状态:A。正常线程结束 B。发生异常,产生异常对象,没有被截获。
C。线程自身调用了Stop()。---不被使用
4.1新生状态:
创建线程对象,可以调用无参,有参(给线程命名)
---可以获得到的信息:
1.获得线程对象。名字 Thread.currentThread().getName()
2.设置或获得当前线程的优先级:
th.setPriority(9);
System.out.println("线程优先级最大是:"+Thread.MAX_PRIORITY);
System.out.println("线程优先级最大是:"+Thread.MIN_PRIORITY);
System.out.println("th1的线程优先级是:"+th.getPriority());
4.2就绪状态:
是否处于就绪状态:Thread.currentThread().isAlive()
4.3运行状态:
程序执行run();【有被执行的资格,同时也被CPU调度。但是至于什么时间被执行的,不清楚】
4.4阻塞状态:
【线程强制执行:join()】
for (int i = 1; i <=10; i++) {
if(i==3){
try {
th.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"--"+i);
}
说明:普通线程强制抢占了cpu资源。
主线程:由原来的运行状态----》阻塞状态---就绪状态---运行状态
普通线程:直接运行结束。
使用场合:线程有明确的【完成先后顺序】。
【线程休眠:sleep()】
for (int i = 1; i <=10; i++) {
if(i==3){
Thread.sleep(3000);//单位是毫秒
}
System.out.println(Thread.currentThread().getName()+"--"+i);
}
说明:(1)当前线程休眠:由原来的运行状态----》阻塞状态---就绪状态---运行状态
---休眠时间结束,进入到就绪状态,等待cpu调度。
(2)中途阻止休眠:(了解)
【例子:】
终止休眠: 1. th.interrupt();
2. 在异常捕获的时候,出现return。
【线程礼让:】
for (int i = 0; i < 10; i++) {
if(i==3){
Thread.yield();
System.out.println("线程礼让一次");
}
System.out.println(i);
}
说明:让出当前这次cpu资源:线程状态不阻塞---直接进行就绪状态--运行状态。
5.线程安全:
多线程同时操作数据资源,会出现数据不正确。所需线程同步。
第一种方式:同步代码块 ---使用在线程中。
public void run() {
for (int i = 1; i <=100; i++) {
synchronized(this){
if(piao>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"--"+piao--);
}
}
}
}
第二种方式:同步方法:
public void run() {
for (int i = 1; i <=100; i++) {
maip();
}
}
public synchronized void maip(){
if(piao>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"--"+piao--);
}
}