多线程认知系列(一)之认识线程、简单实现线程
多线程系列
多线程认知系列(二)之线程的生命周期及安全问题
大家好啊,我是杨洋,今天呢,给大家打来的是多线程系列的讲解,这个系列会贴出真正经过日百万数据量的考验的多线程,那么废话不多说,直接开始了
认识线程
进程与线程
进程是指什么?进程指我们的操作系统开始运行这个程序就把他成为进程。也就是说,一个进程就是一个程序。一个进程可以有多个线程,如QQ视频中同时听到声音、图像、显示字幕。
进程指动态的概念,我们的cpu调度到了一个进程匹配一个程序。线程指的是一个进程开辟多条路径,充分利用我们的CPU。
为什么要认识线程
使用多线程的优点:
- 提高应用程序的响应。对图形化界面更有意义,可增强用户体验。
- 提高计算机系统CPU的利用率
- 改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和修改
线程的创建
首先呢,线程的直接创建有三种方式分别是:
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口
下面贴上各自的实现:
继承Thread类
package com.yanglei.test;
/**
* @author yanglei
* @desc
* @date 2020/8/19
*
* 继承Thread类的过程
* 1.创建一个继承与Thread类的子类
* 2.重写run方法
* 3.创建Thread子类的对象
* 4.调用start方法
*/
//1.创建一个继承与Thread类的子类
class MyThreadTest extends Thread {
//2.重写run方法
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "-----" + i);
}
}
}
public class MyThread {
public static void main(String[] args) {
System.out.println("<<<<<<<<<<<<<<<<<<<<");
//3.创建Thread子类的对象
MyThreadTest myThreadTest1 = new MyThreadTest();
//4.调用start方法
myThreadTest1.start();//start的作用:1.启动当前线程 2.调用当前线程的run方法
for (int i = 0; i < 100; i++) {
System.out.println("main+++++++++:" + i);
}
new MyThreadTest().start();
}
}
实现Runnable接口
package com.yanglei.test;
/**
* @author yanglei
* @desc
* @date 2020/8/20
* 1.创建一个实现了Runnable接口的类
* 2.重写run方法
* 3.创建实现类的对象
* 4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
* 5.调用start()方法
*/
public class RunnableTest {
public static void main(String[] args) {
RunnableDemo runnableDemo = new RunnableDemo();
Thread t1 = new Thread(runnableDemo);
t1.setName("firstThread");
Thread t2 = new Thread(runnableDemo);
t2.setName("secondThread");
t1.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
Thread.currentThread().setName("Mainfangfa");
for (int i = 0; i < 100; i++) {
if (i % 2 == 1) {
System.out.println(Thread.currentThread().getName() + ":::" + i);
}
}
}
}
class RunnableDemo implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":::" + i);
}
}
}
}
实现Callable接口
package com.yanglei.test;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* @author yanglei
* @desc
* @date 2020/8/21
* <p>
* 1.创建一个实现了Callable接口的类
* 2.重写run方法
* 3.创建实现类的对象
* 4.创建FutureTask
* 4.将此对象(FutureTask)作为参数传递到Thread类的构造器中,创建Thread类的对象
* 5.调用start()方法
*/
public class CallableTest {
public static void main(String[] args) {
CallableDemo call = new CallableDemo();
FutureTask<Integer> task = new FutureTask<>(call);
Thread t1 = new Thread(task);
t1.setName("t1:");
t1.start();
Integer integer = null;
try {
integer = task.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println(integer);
}
}
class CallableDemo implements Callable<Integer> {
private int sum = 0;
@Override
public Integer call() throws Exception {
while (true) {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
sum += i;
Thread.sleep(50);
} else {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
return sum;
}
}
}
对比一下继承的方式 vs 实现的方式
两者联系
public class Thread implements Runnable(继承的方式的Thread也实现了Runnable接口)
哪个方式好–肯定是实现啊
- 实现的方式优于继承的方式
- 避免了java单继承的局限性 如果多个线程要操作同一份资源(或数据),更适合使用实现的方式
线程常用方法
Thread 常用的方法
1.start 方法: 启动当前线程,调用线程中的run方法
2.run方法:执行线程的自定义逻辑
3.currentThread: 静态方法,获取当前代码的线程
4.getname:获取当前线程的名称
5.setName:给当前线程命名–也可以通过构造器命名 也可以给线程命名
6.yield():释放当前cpu执行权
7.join():在线程A调用B的join方法,此时线程A会进入阻塞状态,直到线程B执行完了之后,a才会继续执行
8.stop():已过时;强制结束当前线程
9.sleep(time):让当前线程“睡眠”指定的毫秒,当前线程是阻塞状态
10 .isAlive() :判断线程是否存活
线程的优先级
线程的优先级:
2.获取跟设置优先级
getPriority():返回线程的优先级值
setPriority(int newPriority):改变线程的优先级
注:并不是设置的优先级越高就直接执行优先级高的,只是说执行的概率高一点
部分常用方法演示
package com.yanglei.test;
/**
* @author yanglei
* @desc Thread各个方法测试
* @date 2020/8/19
*/
public class ThreadFunctionTest {
public static void main(String[] args) {
ThreadTest t1 = new ThreadTest("ThreadTest1");
t1.setPriority(10);
t1.start();
String name = Thread.currentThread().getName();
Thread.currentThread().setName("Main方法线程");
for (int i = 0; i < 100; i++) {
if (i % 2 == 1) {
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
boolean alive = Thread.currentThread().isAlive();
System.out.println(alive);
}
}
class ThreadTest extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(getName() + "---" + i);
}
if(i == 45){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public ThreadTest(String name) {
super(name);
}
}
总结
- 推荐使用实现的方式实现线程
- 如果需要返回线程run方法里面的数据,实现Callable
- 一般都是实现Runnable接口的
那么,到这里各位朋友应该知道了线程的基础的使用,下一篇的文章会讲解线程遇到的问题以及解决问题的策略,先溜了,掰掰