线程
进程:是系统进行资源分配和调用的独立单位
每个进程都有属于自己的内存资源和系统空间
线程:是CPU执行和调度的基本单位
- 一个进程内部执行多个任务 每个任务为一个线程 一个进程包含一个或多个线程
多线程
- 同一个时间段可以执行多个任务 ————eg:边打游戏边听歌
打游戏和听歌不是同时进行,他们在CPU里来回切换执行 计算机速度很快 我们无法察觉 - 一个时间点 一个CPU只能执行一段代码 因为速度很快 所以有同时执行的错觉
- 优点:提高CPU使用率
解释:程序在运行过程中 线程的运行是由调度器安排调度的——是在抢CPU的时间片,也就是执行权,抢到了时间才能运行
多线程抢到几率比单线程抢到的几率大的多 CPU在多线程中执行的时间比单线程的多 所以提高了程序的使用率
至于多线程中哪个线程能够抢到执行权不确定 所以多线程具有随机性
并行:某一时间内同时运行多个程序——真正的同时
并发:某一时间点同时运行多个程序——来回切换 有同时的错觉
问题:JVM的启动时多线程吗?
——————是的,至少启动了main()的主线程和垃圾回收线程
main( ) :主线程,系统的入口 执行整个程序
线程的创建
JVM虚拟机调用run( ) 方法
run( )中封装的代码是线程必须执行的代码 一般为耗时较长的代码
继承Thread类
- 实现Thread类
- 重写run( )方法
- 实例化类——创建类对象
- 调用start( ) 方法————————启动线程
public class demo extends Thread{
@Override
public void run() {——————————重写run方法
for (int i = 0; i < 10; i++) {
System.out.println("这是线程 "+i);
}
}
public static void main(String[] args) {
demo demo = new demo();————————实例化对象
demo.start();
}
}
实现Runnable接口————推荐使用
优点:避免单继承的局限性 方便一个对象被多个线程使用
- 实现Runnable接口
- 重写run( )方法
- 实例化实际类
- 实例化Thread代理类 传入类对象
- 调用start( )方法
public class demo implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("hello Runnable! "+i);
}
}
public static void main(String[] args) {
demo demo = new demo();
Thread thread = new Thread(demo);
thread.start();
}
}
实现Callable接口
Thread方法
public static Thread currentThread()——获取当前执行的线程
public final String getName()——获取线程名称
public final void setName(String name)——设置线程名称
- Runnable更改线程名称方法 一:
public class RunnableName1 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("子线程名称: "+Thread.currentThread().getName());
}
}
public static void main(String[] args) {
RunnableName1 runnableName1 = new RunnableName1();
Thread thread = new Thread(runnableName1,"我是子"); —————— 设置子线程名称
thread.start();
Thread.currentThread().setName("我是主——"); ————设置主线程名称
for (int i = 0; i < 3; i++) {
System.out.println("主线程名称: "+Thread.currentThread().getName());
} -————————输出:主线程名称: 我是主—— x3 子线程名称: 我是子 x5
}
}
- 更改线程名称方法二:
thread.setName("我是子线程1");
- Thread更改线程名称方法一:
public class Threadname extends Thread {
public Threadname(String name){
super(name);
}
@Override
public void run() {
for (int i = 0; i < 4; i++) {
System.out.println("子线程名称——"+Thread.currentThread().getName());
}
}
public static void main(String[] args) {
Threadname threadname = new Threadname("我是子线程呀");——————直接更改
threadname.start();
Thread.currentThread().setName("主线程!");
for (int i = 0; i < 2; i++) {
System.out.println("主线程名称—"+Thread.currentThread().getName());
}
}
}
- 更改线程名称方法二:
eg: Threadname threadname = new Threadname();
threadname.setName("我是子线程呀!");
线程的状态
- 创建状态:线程一旦创建 就进入了新生状态
- 就绪状态:线程调用start( )方法后的状态 但不一定立即调度执行
- 运行状态:线程抢到了CPU资源后的状态 执行线程体的代码块
- 死亡状态:线程自然执行结束 终止线程 不能再次启动
- 阻塞状态:当调用sleep( ) wait( ) 同步锁定时的状态 代码不往下执行 阻塞解除后 重新进入就绪状态 等待CPU调度执行
public final int getPriority() ——获取线程的优先级 范围:1(min)----10(max)
public final void setPriority(int newPriority)——设置线程的优先级
public final int getPriority()———返回线程的优先级(默认为5)
设置优先级只能使其被CPU分配调度的概率增大 因为多线程具有随机性
public class Threadyouxianji implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("线程名称: "+Thread.currentThread().getName()+"--线程优先级: "+Thread.currentThread().getPriority()+"====循环次数——"+i);
}
}
public static void main(String[] args) {
Threadyouxianji threadyouxianji = new Threadyouxianji();
Thread thread = new Thread(threadyouxianji,"子线程1");
thread.setPriority(Thread.MIN_PRIORITY);
System.out.println(thread.getPriority());——————默认为5
thread.start();
Thread thread2 = new Thread(threadyouxianji, "子线程2222");
thread2.setPriority(Thread.MAX_PRIORITY);
thread2.start();
}
}
public static void sleep(long millis)——线程休眠
public class Threadsleep implements Runnable {
@Override
public void run() {
String[] pome = {"时间一直倒数着","我们许下的快乐" ,"此刻相拥的狂热" ,"却永远都深刻"};
for (int i = 0; i < pome.length; i++) {
System.out.println(pome[i]);
try {
Thread.sleep(1000);———————每一句使线程休眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Threadsleep threadsleep = new Threadsleep();
Thread thread = new Thread(threadsleep);
thread.start();
}
}
public final void join()——线程加入
- 此线程必须执行结束之后 其他线程才能继续执行
public class Threadjoin implements Runnable{
private static boolean b = true;
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("子线程名称 " +Thread.currentThread().getName()+ "; "+ i);
}
}
public static void main(String[] args) {
Threadjoin threadjoin = new Threadjoin();
Thread thread = new Thread(threadjoin,"子线程1号");
thread.start();
Thread.currentThread().setName("我是主线程main");
for (int j = 0; j < 10; j++) {
if(j == 5){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("主线程名称——"+Thread.currentThread().getName()+ "===="+j);
}
}————-输出:.....
主线程名称——我是主线程main====4 ——————当主线程j = 4时 执行子线程
子线程名称 子线程1号; 0 ————————-子线程执行结束后 继续运行主线程
}
public static void yield()——线程礼让
- 暂停当前正在执行的线程对象 并执行其他线程
- 效果不明显——暂停时间过短 其他线程还没有来得及执行就又被此线程抢走了CPU执行权
public class Threadyield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始了");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"线程结束了");
}
public static void main(String[] args) {
Threadyield threadyield = new Threadyield();
Thread thread = new Thread(threadyield,"线程1");
Thread thread2 = new Thread(threadyield, "线程2");
thread.start();
thread2.start();
} ——————————————输出:线程2线程开始了
线程1线程开始了
线程1线程结束了
线程2线程结束了
}
public final void setDaemon(boolean on)——线程守护
- 用户线程:系统的工作线程 用于计算等
- 守护线程:辅助用户线程 eg:内存管理 垃圾回收站
- 步骤
- 创建用户线程类
- 创建守护线程类
- 实例化守护线程类————创建守护对象
- thread.setDaemon( true) ————设置线程为守护线程————在调用start( )之前
- 实例化用户线程类————创建用户对象
- 当用户线程结束 运行的线程都是守护线程时 虚拟机退出——在启动线程之前调用
public class ThreadDaemon{
public static void main(String[] args) {
—————————— 实例化守护线程
Daemon daemon = new Daemon();
Thread thread = new Thread(daemon);
thread.setDaemon(true);
thread.start();
—————————— 实例化用户线程
User user = new User();
Thread thread1 = new Thread(user);
thread1.start();
}
}
class User implements Runnable{ // 用户线程
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"我是用户线程! "+i);
}
}
}
class Daemon implements Runnable{ // 守护线程
@Override
public void run() {
int i = 0;
while(true){
System.out.println(Thread.currentThread().getName()+"守护线程守护你-----"+i);
} ————————————————输出:守护线程开始 用户线程 守护线程结束
}
}
已过时:public final void stop()——强行停止线程的运行
- 停止一个尚未启动的线程是允许的。如果最后启动了该线程,它会立即终止。
public void interrupt()——中断线程
- 可得当线程调用wait(),sleep(long time)方法的时候处于阻塞状态,这个方法可以清除阻塞
public class ThreadStop implements Runnable {
private static boolean flag = true; // 自定义线程停止标志
@Override
public void run() {
int i = 0;
while(flag){
System.out.println("我是子线程——————"+ i++);
}
}
public static void main(String[] args) {
ThreadStop threadStop = new ThreadStop();
Thread thread = new Thread(threadStop);
thread.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+ i);
if(i==5){
ThreadStop.flag = false;
}
}
}
}
龟兔赛跑
public class RaceTest implements Runnable {
private static String Winner = null;
@Override
public void run() {
for (int m = 0; m < 120; m++) {
boolean flag = GameOver(m);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if("兔子".equals(Thread.currentThread().getName()) && m % 30 ==0 ) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"跑了"+m+"米");
if(flag){
break;
}
}
}
private boolean GameOver(int meters) { // 判断比赛结束条件
if (meters == 101) {
Winner = Thread.currentThread().getName();
System.out.println("胜利者是——" + Winner);
return true;
}
if (Winner != null){ // 如果已分出胜负 不用再继续比赛
return true;
}
return false;
}
public static void main(String[] args) {
RaceTest raceTest = new RaceTest();
Thread 兔子 = new Thread(raceTest, "兔子");
Thread 乌龟 = new Thread(raceTest, "乌龟");
兔子.start();
乌龟.start();
}
}