(1)程序,进程,线程
(2)在Java中实现多线程的方式
(3)线程的生命周期
(4)Thread类的常用方法
主要内容
22.1程序,进程,线程
22.1.1程序
程序员使用代码所编写的,用于实现一定功能的代码的指令集合,称作程序
22.1.2进程
启动的程序,称为进程
进程:cpu, data,code
每个进程之间都是相互独立的,一个进程的结束, 不会影响其它的进程
进程与进程之间的切换效率低,一个进程至少有一个线程,负责具体的执行
22.1.3线程
线程是进程的组成部分,用于执行
一个进程中,由N多个线程组成,这N多个线程共享同一块内存 ,线程之间的切换效率高
举例:
高速公路:
(1)修路 --》修完 -->程序
(2)通车 -- ------------>进程
(3)N多条车道 ----->双向8车道 (同一方向同时并行4台车)
一个线程的结束,不一定会结束进程
进程的结束,线程都将结束
22.2Java中实现多线程的方式
22.2.1继承Thread类
(1)继承 Thread类
(2)重写run方法 ,在run方法中所编写的代码称为线程体
package com.bjsxt.thread;
public class MyThread extends Thread{ //MyThread这个类具备了多线程操作执行的能力
@Override
public void run() {
//线程体
System.out.println("run方法");
}
}
(3)启动线程
package com.bjsxt.thread;
public class TestMyThread {
public static void main(String[] args) {
//主线程 ,负责java程序的运行
MyThread my=new MyThread();//创建自定义的线程对象
/**启动线程*/
my.start();
System.out.println("主线程..............");
}
}
这是一个应用程序,开始运行执行--》进程-->有现个线程, (主线程,MyThread的线程对象my)
在线程体中使用循环,可以让“抢占”CPU的效率更加明显
package com.bjsxt.thread;
public class MyThread2 extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//Thread.currentThread()用于获取当前线程对象, getName(),用于获取线程的名称
System.out.println(Thread.currentThread().getName()+"--------->"+i);
}
}
}
package com.bjsxt.thread;
public class TestMyThreadw2 {
public static void main(String[] args) {
//创建线程类的对象
MyThread2 my=new MyThread2();
//启动线程
my.start();
//主线程中的循环
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"====================="+i);
}
}
}
22.2.2实现Runnable接口
package com.bjsxt.runnable;
public class MyRunnbale implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//Thread.currentThread()用于获取当前线程对象, getName(),用于获取线程的名称
System.out.println(Thread.currentThread().getName()+"--------->"+i);
}
}
}
测试
package com.bjsxt.runnable;
public class TestMyRun {
public static void main(String[] args) {
//创建线程类的对象
MyRunnbale my=new MyRunnbale();
//启动线程
Thread t=new Thread(my);
//t.run();
t.start();//调用的是MyRunnbale类中的run方法中的代码
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"====================="+i);
}
}
}
Thread t=new Thead(my);
调用Thread类中的带参构造方法
带参构造方法中的代码,杨老师的简代写法
public Thread(Runnable target){
this.target=target;
threadInitNumber++;
线程的默认命名方式 "Thread-"+threadInitNumber
}
Thread类的定义
public class Thread
extends Object
implements Runnable
MyRunnbale类的定义 (杨老师自定义的线程类)
public class MyRunnbale implements Runnable {
}
说明Thread类与自定义的线程类都实现了共同的接口,Runnable接口,把这种形式,称为“代理设计模式”
22.3代理设计模式
婚庆公司 (专业)
你要结婚
共同的接口: Marry接口 -->方法,结婚的方法 marry()
婚庆 布置会场,组织车队 (白头偕老...) ,司仪,。。打扫会场
你 --》结婚
总结:
(1)程序,进程,线程
(2)在Java中实现多线程的方式
继承Thread类
实现Runnable接口
(3)代理设计模式 (原理理解)
真实角色
代理角色
(1)真实角色与代理角色实现/继承同一个接口/父类
(2)接口作为代理类中的私有属性
(3)代理类中编写带参构造方法 (接口作方法的形式参数)
(4)测试
创建真实角色对象
创建代理类对象 (真实角色)
代理类的对象.调用方法
开发中使用实现接口的形式实现多线程操作?
(1)因为java中的类为单继承,一旦继承Thread类,不允许其它的类
(2)实现接口的形式,可以实现资源的共享
继承Thread类
package com.bjsxt.ticket;
public class TicketThread extends Thread{
public TicketThread(String threadName){
super(threadName);//调用父类Thread类中带参构造方法
}
private int ticket=5;//5张票
@Override
public void run() {
for (int i = 0; i <100; i++) {
if (ticket>0) {
System.out.println(Thread.currentThread().getName()+"买第"+(ticket--)+"张票");
}
}
}
}
测试
package com.bjsxt.ticket;
public class TestTicketThread {
public static void main(String[] args) {
//创建一个线程类的对象
TicketThread th1=new TicketThread("A窗口");
TicketThread th2=new TicketThread("B窗口");
TicketThread th3=new TicketThread("C窗口");
//同时卖票
th1.start();
th2.start();
th3.start();
}
}
实现Runnable接口
package com.bjsxt.ticket;
public class TicketRunnable implements Runnable {
private int ticket=5;
@Override
public void run() {
for (int i = 0; i <100; i++) {
if (ticket>0) {
System.out.println(Thread.currentThread().getName()+"买第"+(ticket--)+"张票");
}
}
}
}
测试:
package com.bjsxt.ticket;
public class TestTicketRunnable {
public static void main(String[] args) {
//创建线程类对象
TicketRunnable tr=new TicketRunnable();
//创建三个代理
Thread t1=new Thread(tr, "A窗口");
Thread t2=new Thread(tr, "B窗口");
Thread t3=new Thread(tr, "C窗口");
//启线程
t1.start();
t2.start();
t3.start();
}
}
22.3线程的生命周期
首先你不知道什么时候会被挑中执行(就绪状态);第二,在执行的过程中随时可能被打断(时间片到了),让出CPU车间(就绪);第三,一旦出现硬盘、数据库这样耗时的操作,也得让出CPU去等待(阻塞);第四,就是数据来了,你也不一定马上执行,还得等着(就绪)CPU挑选
线程(正常) 就绪<--->运行
(等待资源) 运行-->阻塞状态-->就绪-->运行状态
22.4Thread类的常用方法
import com.bjsxt.thread.MyThread;
public class TestMethod {
public static void main(String[] args) {
//用于获取当前线程类的对象
Thread t=Thread.currentThread();
System.out.println(t);
System.out.println(t.toString());
/**Thread[main,5,main]
* main -->getName()线程的名称
* 5 -->getPriority()线程的优先级
* main---- >group.getName()线程组的名称*/
//创建了一个线程
MyThread my=new MyThread();
System.out.println(my);
/**Thread[Thread-0,5,main]
* Thread-0 :线程的名称
* 5-->线程的优先级
* main-->线程组的名称
* **/
ThreadGroup tg=new ThreadGroup("线程组A"); //创建一个线程组
//Thread类的带参构造方法
Thread tt=new Thread(tg, my);
System.out.println(tt);
/**Thread[Thread-1,5,线程组A]
* Thread-1-->线程的名称
* 5-->线程的优先级
* 线程组A---》线程组的名称
* */
}
}
(2)String getName(),void setName(String name) 获取和设置线程的名称
int getPriority() , void setPriority(int newPriority ) 获取和设置线程的优先级
package com.bjsxt.method;
public class TestPriority {
public static void main(String[] args) {
//获取当前线程对象
Thread t=Thread.currentThread();
System.out.println(t);
t.setName("A线程");
t.setPriority(Thread.MAX_PRIORITY);
System.out.println(t);
System.out.println("最小优先级:"+Thread.MIN_PRIORITY);
System.out.println("默认优先级:"+Thread.NORM_PRIORITY);
System.out.println("线程的名称:"+t.getName());
System.out.println("线程的优先级:"+t.getPriority());
}
}
(3)boolean isAlive()判断线程是否处于活动状态
就绪与运行 true
终止状态 false
package com.bjsxt.method;
import com.bjsxt.thread.MyThread2;
public class TestIsAlive {
public static void main(String[] args) {
//创建线程类的对象
MyThread2 my=new MyThread2(); //新生状态
System.out.println("新生状态:"+my.isAlive());
my.start();//启动线程,就绪状态 ,运行状态
System.out.println("启动之后:"+my.isAlive());
//主线程中代码
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"=============="+i);
}
System.out.println("主线程结束:"+my.isAlive());
}
}
(4)void join() 调用该方法的线程,强制执行,导致其它线程阻塞,有一个检查时异常 InterruptedException
import com.bjsxt.thread.MyThread2;
public class TestJoin {
public static void main(String[] args) throws InterruptedException {
//创建一个线程类对象
MyThread2 my=new MyThread2();
my.start();//启动线程
//主线程中
for (int i = 0; i < 10; i++) {
if (i==4) {
my.join();//my这个线程强制执行,主线程阻塞
}
System.out.println(Thread.currentThread().getName()+"=============="+i);
}
}
}
(5)static void sleep(int millsecond)毫秒 线程休眠,导致当前线程进入阻塞状态
package com.bjsxt.method;
public class MyThread implements Runnable {
@Override
public void run() {
System.out.println("1.进行run方法");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("2.休眠结束");
}
}
测试:
package com.bjsxt.method;
public class ThreadSleep {
public static void main(String[] args) throws InterruptedException {
// 创建线程类的对象
MyThread my=new MyThread();
//创建代理类的匿名对象,调用 start()方法
new Thread(my).start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"==========="+i);
}
}
}
(6)static void yield()线程的礼让,只礼让一次,当前线程进入就绪状态
package com.bjsxt.method;
import com.bjsxt.thread.MyThread2;
public class TestYield {
public static void main(String[] args) {
// 创建线程类的对象
MyThread2 my = new MyThread2();
my.start();// 启动线程
// 主线程中代码
for (int i = 0; i < 10; i++) {
if (i==3) {
Thread.yield(); //主线礼让
System.out.println("主线程礼让");
}
System.out.println(Thread.currentThread().getName() + "==============" + i);
}
}
}