更新时间:2022-06-14 12:25:30
多线程<small>创建线程的三种方式</small>
几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序就是一个进程Process。当一个程序运行时,内部可能包含多个顺序执行流,每个顺序执行流就是一个线程Thread。
线程是进程的组成部分,一个进程可以拥有多个线程,一个线程必须拥有一个父进程。
线程可以拥有自己的堆栈,自己的程序计数器和自己的局部变量,但是线程不拥有自己的资源。它与父进程的其他线程共享该进程的所有资源。
线程的执行是抢占式的,所以任何一个线程都有可能被挂起,以便另外一个线程的执行。
线程可以创建和撤销另外一个线程。
线程共享的环境包括:进程的代码段,进程的共有数据等。利用这些共享的数据,线程很容易实现项目之间的通信。
currenThread(),获取当前线程对象
getName(),当前线程的名字,默认是main ,Thread-0,Thread-1,Thread-n
package com.manyThread;
/**
* @author futao
* Created on 18-1-8-下午8:49.
* 多线程的实现方式1,继承Thread类,重写run()方法
*/
public class FirstThread extends Thread {
private int i;
@Override
public void run() {
for (; i < 1000; i++) {
System.out.println("==" + this.getName() + " " + i);
}
}
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
System.out.println("main===" + Thread.currentThread().getName() + " " + i);
if (i == 20) {
FirstThread firstThread = new FirstThread();
firstThread.setName("Niu");
firstThread.start();
new FirstThread().start();
}
}
}
}
可以发现,i的值是不连续的,所以用继承Thread的方式实现的多线程是不能够共享线程的实例变量的。
使用继承Thread类的方法来创建线程时,多个线程之间无法共享线程的实例变量,因为每个线程都需要实例化一个对象。
package com.manyThread;
/**
* @author futao
* Created on 18-1-8-下午9:10.
* 多线程的实现方式2,实现Runnable接口,重写run()方法
*/
public class FirstRunnable implements Runnable {
private int i;
@Override
public void run() {
for (; i < 1000; i++) {
System.out.println(Thread.currentThread().getName() + "===" + i);
}
}
public static void main(String[] args) {
for (int j = 0; j < 100; j++) {
System.out.println("main" + j);
if (j == 20) {
FirstRunnable firstRunnable = new FirstRunnable();
/*Runnable的实现类的对象仅仅用来作为new Thread()的target*/
Thread thread = new Thread(firstRunnable, "myNewThread");
thread.start();
Thread thread1 = new Thread(firstRunnable, "2thread");
thread1.start();
}
}
}
}
变量 i 的值是连续的,所以通过实现Runnable接口的方式实现的多线程是可以共享线程类的实例变量的
这是因为在这种方式下,程序所创建的Runnable对象只是线程的target,而多个线程可以共享同一个target,所以多个线程可以共享同一个线程类(实际上是线程的target类)的实例变量。
所以通过实现Runnable接口创建的多线程时,Thread
类的作用就是把run()方法包装成线程执行体。
Runnable接口的增强版
package com.manyThread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* @author futao
* Created on 18-1-11-上午10:21.
*/
public class FirstCallable implements Callable {
@Override
public Object call() throws Exception {
return 6666;
}
public static void main(String[] args) {
// FirstCallable firstCallable = new FirstCallable();
// FutureTask futureTask = new FutureTask(firstCallable);
// Thread thread = new Thread(futureTask);
// thread.start();
// try {
// System.out.println(futureTask.get());
// } catch (InterruptedException e) {
// e.printStackTrace();
// } catch (ExecutionException e) {
// e.printStackTrace();
// }
FutureTask futureTask1 = new FutureTask(() -> {
int i = 0;
for (; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
return i;
});
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread().getName() + i);
if (i == 20) {
Thread thread = new Thread(futureTask1);
thread.start();
try {
/*get()方法将导致主线程被阻塞,直到call()方法结束并返回返回值为止*/
System.out.println(futureTask1.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
}