Java多线程是一种并发编程方式,允许Java应用程序同时执行多个独立任务。它通过创建和管理多个线程来实现,
每个线程代表一个独立的执行流。多线程可以提高程序性能、资源利用率和响应能力。Java提供了Thread类和Runnable接口来创建和操作线程,
还包括同步机制(synchronization)来确保线程安全。多线程适用于处理并行计算、异步操作、GUI编程等场景。然而,多线程编程也需要小心处理竞态条件、死锁等问题,以确保程序正确运行。
🌊 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗
在操作系统中,安装了多个程序,并行指的是在一段时间内宏观上有多个程序同时运行,这在单 CPU 系统中,每一时刻只能有一道程序执行,即
微观上这些程序是分时的交替运行,只不过是给人的感觉是同时运行,那是因为分时交替运行的时间是非常短的。
而在多个 CPU 系统中,则这些可以并发执行的程序便可以分配到多个处理器上(CPU),实现多任务并行
执行,即利用每个处理器来处理一个可以并发执行的程序,这样多个程序便可以同时执行。目前电脑市场上说的多核 CPU,便是多核处理器,核
越多,并行处理的程序越多,能大大的提高电脑运行的效率。
打开活动监视器
● 分时调度
所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
● 抢占式调度
优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。
大部分操作系统都支持多进程并行运行,现在的操作系统几乎都支持同时运行多个程序。比如:现在我们上课一边使用编辑器,一边使用录屏软件,同时还开着画图板,dos窗口等软件。此时,这些程序是在同时运行,”感觉这些软件好像在同一时刻运行着“。
实际上,CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而言,某个时刻,只能执行一个线程,而
CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是在同一时刻运行。
其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高。
示例:
public class MyThread extends Thread {
//定义指定线程名称的构造方法
public MyThread(String name) {
//调用父类的String参数的构造方法,指定线程的名称
super(name);
}
/**
* 重写run方法,完成该线程执行的逻辑
*/
@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println(getName() + ":" + i);
}
}
}
测试
public class Demo1 {
public static void main(String[] args) {
//创建自定义线程对象
MyThread mt = new MyThread("新建的线程");
//开启新线程
mt.start();
//在主方法中执行for循环
for (int i = 0; i < 10; i++) {
System.out.println("主线程:" + i);
}
}
}
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
测试
public class Demo2 {
public static void main(String[] args) { //创建自定义类对象 线程任务对象
MyRunnable mr = new MyRunnable();
//创建线程对象
Thread t = new Thread(mr, "新建的线程");
t.start();
for (int i = 0; i < 20; i++) {
System.out.println("主线程" + i);
}
}
}
继承Thread 和实现Runnable的区别
如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。总结:*
*实现Runnable接口比继承Thread类所具有的优势**:
方法名 | 说明 |
---|---|
public static void sleep(long millis) | 当前线程主动休眠 millis 毫秒。 |
public static void yield() | 当前线程主动放弃时间片,回到就绪状态,竞争下一次时间片。 |
public final void join() | 允许其他线程加入到当前线程中。 |
public void setPriority(int) | 线程优先级为1-10,默认为5,优先级越高,表示获取CPU机会越多。 |
public void setDaemon(boolean) | 设置为守护线程线程有两类:用户线程(前台线程)、守护线程(后台线程) |
setPriority()
来设置线程的优先级别static int MAX_PRIORITY 线程可以具有的最高优先级,取值为10。 static int MIN_PRIORITY 线程可以具有的最低优先级,取值为1。 static int NORM_PRIORITY 分配给线程的默认优先级,取值为5。
示例:
/**
* 优先级
*
*/
public class PriorityThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread().getName() + "============" + i);
}
}
}
测试:
public class TestPriority {
public static void main(String[] args) {
PriorityThread p1 = new PriorityThread();
p1.setName("p1");
PriorityThread p2 = new PriorityThread();
p2.setName("p2");
PriorityThread p3 = new PriorityThread();
p3.setName("p3");
p1.setPriority(1);
p3.setPriority(10);
//启动
p1.start();
p2.start();
p3.start();
}
}
使用线程的 sleep()
可以使线程休眠指定的毫秒数,在休眠结束的时候继续执行线程
示例:
class SleepThread extends Thread {
@Override
public void run() {
String[] names = new String[]{"zs", "ls", "ww", "z6"};
int index = (int) (Math.random() * 4);
for (int i = 3; i > 0; i--) {
System.out.println(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("倒计时:" + i);
}
System.out.println("抽中学员为:" + names[index]);
}
}
测试:
public class TestSleep {
public static void main(String[] args) {
new SleepThread().start();
}
}
Thread.yield()
方法作用是:暂停当前正在执行的线程对象(及放弃当前拥有的cup资源),并执行其他线程。yield()
做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用 yield()
的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证 **yield()**
达到让步目的
,因为让步的线程还有可能被线程调度程序再次选中。示例:
class Task1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("A:" + i);
}
}
}
class Task2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("B:" + i);
Thread.yield();
}
}
}
public class Demo {
public static void main(String[] args) {
new Thread(new Task2()).start();
new Thread(new Task1()).start();
}
}
sleep()和yield()的区别
sleep()使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会被执行;
yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
sleep 方法使当前运行中的线程睡眼一段时间,进入不可运行状态,这段时间的长短是由程序设定的,yield 方法使当前线程让出 CPU
占有权,但让出的时间是不可设定的。实际上,yield()方法对应了如下操作:先检测当前是否有相同优先级的线程处于同可运行状态,如有,则把
CPU 的占有权交给此线程,否则,继续运行原来的线程。所以yield()方法称为“退让”,它把运行机会让给了同等优先级的其他线程
另外,sleep 方法允许较低优先级的线程获得运行机会,但 yield() 方法执行时,当前线程仍处在可运行状态,所以,不可能让出较低优先级的线程些时获得
CPU 占有权。在一个运行系统中,如果较高优先级的线程没有调用 sleep 方法,又没有受到 I\O
阻塞,那么,较低优先级线程只能等待所有较高优先级的线程运行结束,才有机会运行。
Thread
中,join()
方法的作用是调用线程等待该线程完成后,才能继续往下运行。示例:
class JoinThread extends Thread {
public JoinThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程开始运行");
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "-->子线程:" + i);
}
System.out.println(Thread.currentThread().getName() + "线程结束运行");
}
}
public class JoinDemo {
public static void main(String[] args) {
System.out.println("主线程开始运行。。。");
// 新加入的子线程
JoinThread t1 = new JoinThread("新加入的线程");
t1.start();
// try {
// t1.join();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println("主线程开始结束。。。");
}
}
本期结束咱们下次再见👋~
🌊 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。