javaAPI_多线程基础_多线程基础1

Posted 德墨特尔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javaAPI_多线程基础_多线程基础1相关的知识,希望对你有一定的参考价值。


多线程基础1

1.如何实现多线程?
由于线程是依赖进程而存在的,所以我们应该先创建一个进程出来。
而进程是由系统创建的,所以我们应该去调用系统功能创建一个进程。
Java是不能直接调用系统功能的,所以,我们没有办法直接实现多线程程序。
但是呢?Java可以去调用C/C++写好的程序来实现多线程程序。
由C/C++去调用系统功能创建进程,然后由Java去调用这样的东西,
然后提供一些类供我们使用。我们就可以实现多线程程序了

通过查看API,我们知道了有2中方式实现多线程程序


2.创建线程的方式1:继承Thread类

(1).步骤:
A:自定义类MyThread继承Thread类。
B:MyThread类里面重写run()?
为什么是run()方法呢?
C:创建对象
D:启动线程

(2).为什么在继承Thread的方法的时候需要重写run()方法呢?
不是类中的所有代码都需要被线程执行的。
而这个时候,为了区分哪些代码能够被线程执行,java提供了Thread类中的run()用来包含那些被线程执行的代码.


(3).哪一些代码适合加入到线程中呢?
一般来说,被线程执行的代码肯定是比较耗时的


(4).一个多线程实现的基本代码:
//线程类
public class MyThread extends Thread {
@Override
public void run() {
for (int x = 0; x < 200; x++) {
System.out.println(x);
}
}
}

//测试类
public static void main(String[] args) {
// 创建两个线程对象
MyThread my1 = new MyThread();
MyThread my2 = new MyThread();

my1.start();
my2.start();
}


(5).相关注意事项
面试题:run()和start()的区别?
run():仅仅是封装被线程执行的代码,直接调用是普通方法
start():首先启动了线程,然后再由jvm去调用该线程的run()方法。


(6).异常
IllegalThreadStateException:非法的线程状态异常
为什么呢?因为这个相当于是my线程被调用了两次。而不是两个线程启动。也就是说同一个线程不可以被启动俩次。

 

3.多线程的基本操作_获取线程名称

(1).获取线程对象的名称
public final String getName():获取线程的名称。

(2).设置线程对象的名称
public final void setName(String name):设置线程的名称

(3).针对不是Thread类的子类中如何获取线程对象名称呢?
public static Thread currentThread():返回当前正在执行的线程对象
Thread.currentThread().getName()

(4).基本功能相关测试
//多线程类
public class MyThread extends Thread {

public MyThread() {
}

public MyThread(String name){
super(name);
}

@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(getName() + ":" + x);
}
}
}

//测试类
public static void main(String[] args) {
// 创建线程对象
//无参构造+setXxx()
// MyThread my1 = new MyThread();
// MyThread my2 = new MyThread();
// //调用方法设置名称
// my1.setName("张三");
// my2.setName("李四");
// my1.start();
// my2.start();

//带参构造方法给线程起名字[这里面需要在多线程类中添加带参构造方法传入到其父类中去]
// MyThread my1 = new MyThread("张三");
// MyThread my2 = new MyThread("李四");
// my1.start();
// my2.start();

//我要获取main方法所在的线程对象的名称,该怎么办呢?
//遇到这种情况,Thread类提供了一个很好玩的方法:
//public static Thread currentThread():返回当前正在执行的线程对象
System.out.println(Thread.currentThread().getName());
}


4.线程调度以及设置线程的优先级

(1).线程调度的意义
假如我们的计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到 CPU时间片,也就是使用权,才可以执行指令。

(2).线程调度的俩种模型
A:分时调度模型
所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片
B:抢占式调度模型
优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些。
Java使用的是抢占式调度模型。

(3).获取线程对象的优先级
public final int getPriority():返回线程对象的优先级

(4).如何设置线程对象的优先级呢?
public final void setPriority(int newPriority):更改线程的优先级。

注意:
线程默认优先级是5。
线程优先级的范围是:1-10。
线程优先级高仅仅表示线程获取的 CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到比较好的效果。

(5).代码:
public static void main(String[] args) {
ThreadPriority tp1 = new ThreadPriority();
ThreadPriority tp2 = new ThreadPriority();
ThreadPriority tp3 = new ThreadPriority();

tp1.setName("东方不败");
tp2.setName("岳不群");
tp3.setName("林平之");

// 获取默认优先级
// System.out.println(tp1.getPriority());
// System.out.println(tp2.getPriority());
// System.out.println(tp3.getPriority());

// 设置线程优先级--IllegalArgumentException:非法参数异常。
// tp1.setPriority(100000);

//设置正确的线程优先级
tp1.setPriority(10);
tp2.setPriority(1);

tp1.start();
tp2.start();
tp3.start();
}

//多线程执行的代码
public class ThreadPriority extends Thread {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(getName() + ":" + x);
}
}
}


5.线程控制之休眠线程

(1).相关方法
public static void sleep(long millis):让线程休眠指定时间

(2).代码体现
//线程类
public class ThreadSleep extends Thread {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(getName() + ":" + x + ",日期:" + new Date());
// 睡眠
// 困了,我稍微休息1秒钟
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//测试类
public static void main(String[] args) {
ThreadSleep ts1 = new ThreadSleep();
ThreadSleep ts2 = new ThreadSleep();
ThreadSleep ts3 = new ThreadSleep();

ts1.setName("张三");
ts2.setName("李四");
ts3.setName("王五");

ts1.start();
ts2.start();
ts3.start();
}


6.线程控制之加入线程

(1).相关方法
public final void join():等待该线程终止。也就是存在着先后顺序,先有父后有子


(2).相关代码
//线程类
public class ThreadJoin extends Thread {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(getName() + ":" + x);
}
}
}

//测试类
public static void main(String[] args) {
ThreadJoin tj1 = new ThreadJoin();
ThreadJoin tj2 = new ThreadJoin();
ThreadJoin tj3 = new ThreadJoin();

tj1.setName("李渊");
tj2.setName("李世民");
tj3.setName("李元霸");

tj1.start();
try {
tj1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

tj2.start();
tj3.start();
}


6.线程控制之礼让线程

(1).相关方法
public static void yield():暂停当前正在执行的线程对象,并执行其他线程。在一定程度上可以保证程序的执行更和谐一些。
但是无法保证每一个线程执行一次。

(2).相关代码
//线程类
public class ThreadYield extends Thread {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(getName() + ":" + x);
Thread.yield();
}
}
}

//测试类
public static void main(String[] args) {
ThreadYield ty1 = new ThreadYield();
ThreadYield ty2 = new ThreadYield();

ty1.setName("林青霞");
ty2.setName("刘意");

ty1.start();
ty2.start();
}

7.线程控制之守护线程[也叫后台线程]

(1).相关方法
public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程。
当正在运行的线程都是守护线程时,Java 虚拟机退出。 该方法必须在启动线程前调用。

(2).代码测试
//线程类代码
public class ThreadDaemon extends Thread {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(getName() + ":" + x);
}
}
}
//测试类代码
public static void main(String[] args) {
ThreadDaemon td1 = new ThreadDaemon();
ThreadDaemon td2 = new ThreadDaemon();

td1.setName("关羽");
td2.setName("张飞");

// 设置收获线程[守护刘备,for循环结束以后,后面的线程不再执行]
td1.setDaemon(true);
td2.setDaemon(true);

td1.start();
td2.start();

Thread.currentThread().setName("刘备");
for (int x = 0; x < 5; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}


7.线程控制之中断线程[*****]

(1).相关方法
public final void stop():让线程停止,过时了,但是还可以使用。
public void interrupt():中断线程。 把线程的状态终止,并抛出一个InterruptedException。

(2).测试代码
//线程类代码
public class ThreadStop extends Thread {
@Override
public void run() {
System.out.println("开始执行:" + new Date());

// 我要休息10秒钟,亲,不要打扰我哦
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// e.printStackTrace();
System.out.println("线程被终止了");
}

System.out.println("结束执行:" + new Date());
}
}

//测试类代码
public static void main(String[] args) {
ThreadStop ts = new ThreadStop();
ts.start();

// 你超过三秒不醒过来,我就干死你
try {
Thread.sleep(3000);
// ts.stop();过时,但是不建议使用
ts.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}


8.线程的生命周期


以上是关于javaAPI_多线程基础_多线程基础1的主要内容,如果未能解决你的问题,请参考以下文章

java基础第八天_多线程

Java基础_多线程2[线程控制]

BigDataJava基础_多线程

尚硅谷_Java零基础教程(多线程)-- 学习笔记

IT十八掌作业_java基础第八天_多线程

阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第5节 线程池_1_线程池的概念和原理