1.并发和并行
2.多线程的三种实现方式
2.1 方式1 继承Thread类的方式进行实现
package DuoXianCheng.ThreadDemo1;
public class Demo1 {
public static void main(String[] args) {
/*多线程的第一种启动方式
* 1.自己定义一个类继承Thread
* 2.重写里面的run方法
* 3.创建子类的对象,并启动线程*/
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
//开启线程
myThread1.start();
myThread1.setName("线程1");
myThread2.start();
myThread2.setName("线程2");
// long start1 = System.currentTimeMillis();
// for (int i = 0; i < 1000; i++) {
// System.out.println("非多线程");
// }
// long end1 = System.currentTimeMillis();
// System.out.println("不开启多线程消耗时间:"+(end1-start1));
}
}
package DuoXianCheng.ThreadDemo1;
public class MyThread extends Thread{
@Override
public void run() {
//书写线程要执行的方法
for (int i = 0; i < 1000; i++) {
System.out.println(getName()+"多线程");
}
}
}
2.2 方式2 实现Runnable接口的方式实现
package DuoXianCheng.ThreadDemo2;
public class Demo2 {
public static void main(String[] args) {
/*多线程的第二种启动方式
* 1.自己定义一个类实现Runnable接口
* 2.重写里面的run方法
* 3.创建自己的类的对象
* 4.创建一个Thread类的对象,并开启线程*/
/*创建runnable的对象*/
MyThread2 myThread2 = new MyThread2();
/*创建线程自己的对象*/
Thread thread1 = new Thread(myThread2);
Thread thread2 = new Thread(myThread2);
thread1.setName("进程1");
thread2.setName("进程2");
thread1.start();
thread2.start();
}
}
package DuoXianCheng.ThreadDemo2;
public class MyThread2 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
/**由于没有继承Thread类,需要先获取到当前线程才能拿到名字 ,Thread t = Thread.currentThread();*/
System.out.println(Thread.currentThread().getName()+"hello");
}
}
}
2.3 方式3 利用Callable接口和Future接口方式实现
package DuoXianCheng.ThreadDemo3;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Demo3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
/**多线程的第三种实现方式:
* 1.创建一个类MyCallable实现Callable接口
* 2.重写call(是有返回值的,表示多线程运行的结果)
* 3.创建MyCallable的对象(表示多线程要执行的任务)
* 4.创建FutureTask的对象(作用管理多线程运行的结果)
* 5.创建Thread类的对象,并启动(表示线程)*/
MyThread3 myThread3 = new MyThread3();
FutureTask<Object> objectFutureTask = new FutureTask<Object>(myThread3);
Thread thread = new Thread(objectFutureTask);
thread.start();
System.out.println(objectFutureTask.get());
}
}
package DuoXianCheng.ThreadDemo3;
import java.util.concurrent.Callable;
public class MyThread3 implements Callable {
@Override
public Object call() throws Exception {
int num =0;
for (int i = 0; i < 10; i++) {
num+=i;
}
return num;
}
}
3.多线程常用的成员方法
package DuoXianCheng.ThreadMethod;
public class ThreadDemo4 {
public static void main(String[] args) throws InterruptedException {
/**
String getName() 返回此线程的名称
void setName(String name) 设置线程的名字(构造方法也可以设置名字)
细节:
1、如果我们没有给线程设置名字,线程也是有默认的名字的格式: Thread-X (X序号,从@开始的)
static Thread currentThread() 获取当前线程的对象
细节:
当JVM虚拟机启动之后,会自动的启动多条线程
其中有一条线程就叫做main线程
他的作用就是去调用main方法,并执行里面的代码
在以前,我们写的所有的代码,其实都是运行在main线程当中
static void sleep(long time) 让线程休眠指定的时间,单位为毫秒
*/
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
MyThread myThread3 = new MyThread("坦克");
myThread1.start();
myThread2.start();
// System.out.println("线程休眠前");
// MyThread.sleep(5000);
// System.out.println("休眠结束");
}
}
package DuoXianCheng.ThreadMethod;
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
MyThread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName()+"@"+i);
}
}
public MyThread() {
}
public MyThread(String name) {
super(name);
}
}
设置名字除了getName 还可以在构造方法里面选择第一个和第四个
3.1线程的优先级
线程默认优先级5,最低1,最高10,优先级越高,抢占cpu概率越高。
package DuoXianCheng.ThreadMethod2;
public class ThreadDemo5 {
public static void main(String[] args) {
//setPriority(int newPriority)设置线程的优先级 final int getPriority()获取线程的优先级
//1.创建参数对象
MyThread2 myThread2 = new MyThread2();
//2.创建线程对象
Thread thread1 = new Thread(myThread2,"坦克");
Thread thread2 = new Thread(myThread2,"飞机");
//打印默认优先级(默认是5 最小1 最大10 优先级越高,抢到cpu概率越大)
System.out.println(thread1.getPriority());
System.out.println(thread2.getPriority());
}
}
package DuoXianCheng.ThreadMethod2;
public class MyThread2 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+"------"+i);
}
}
}
3.2守护线程
主方法
package DuoXianCheng.ThreadMethod3;
public class TestShouHu {
public static void main(String[] args) {
/**
* final void setDaemon(boolean on) 设置为守护线程
* 细节:当其他的非守护线程执行完毕之后,守护线程会陆续结束(运行一会结束)
* 通俗易懂:当女神线程结束了,那么备胎也没有存在的必要了*/
BeiTaiThread beiTaiThread = new BeiTaiThread();
NvShenThread nvShenThread = new NvShenThread();
beiTaiThread.setName("守护线程");
nvShenThread.setName("非守护线程");
//设置备胎线程为守护线程
beiTaiThread.setDaemon(true);
beiTaiThread.start();
nvShenThread.start();
}
}
备胎线程
package DuoXianCheng.ThreadMethod3;
public class BeiTaiThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+"@"+i);
}
}
}
女神线程
package DuoXianCheng.ThreadMethod3;
public class NvShenThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+"@"+i);
}
}
}
3.3守护线程
运用的较少,执行完线程后让出cpu,重新争夺cpu,尽可能保持均衡,但由于两个线程间优先级都是5,很可能再次抢到。
Thread.yield()
3.4插入线程
插入后,会先执行完再执行别的线程。
Thread thread1 = new Thread();
thread1.join();