在多线程的操作之中,大多数情况下使用的是Thread
的start()
,如果对于多线程需要进行停止处理,Thread
提供有stop()
,但是其在 JDK 1.2开始就不被推荐使用了。要想停止线程,则需要选择一种柔和的形式。
public class Test {
public static boolean flag = true;
public static void main(String[] args) throws InterruptedException {
new Thread(
() -> {
long num = 0;
while (flag) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "运行中 num = " + num++);
}
},
"执行线程")
.start();
Thread.sleep(200);
flag = false;
}
}
万一有其他的线程控制 flag 的内容,对于线程的停止并不是立刻停止的,而是通过判断 flag 的值来完成的。
只能是为一个活着的线程进行守护,死了的线程不会守护。如果主线程的程序或者其他线程还在执行的时候,那么守护线程将一直存在,并且运行在后台。
在Thread
中提供有如下的守护线程操作方法。
public final void setDaemon(boolean on)
public final boolean isDaemon()
public class Test {
public static boolean flag = true;
public static void main(String[] args) throws InterruptedException {
Thread userThraed =
new Thread(
() -> {
for (int x = 0; x < 10; x++)
System.out.println(Thread.currentThread().getName() + "运行中 x = " + x);
},
"用户线程");
Thread daemonThread =
new Thread(
() -> {
for (int x = 0; x < Integer.MAX_VALUE; x++)
System.out.println(Thread.currentThread().getName() + "运行中 x = " + x);
},
"守护线程");
daemonThread.setDaemon(true); // 设置为守护线程,随着整体程序而存在。
userThraed.start();
daemonThread.start();
}
}
在整个 JVM 中,最大的守护线程就是 GC 线程。程序执行完毕,GC 线程也将消失。
在多线程定义之中,Volatile 主要是在属性定义上使用的,表示该属性为直接数据操作,而不进行副本的复制处理。
注意:此属性并不是描述同步的。
在正常进行变量处理时往往会经历如下步骤。
如果一个属性上追加了Volatile
,则表示不使用副本,直接操作原变量。
volatile
主要在属性上使用,synchronized
是在代码块、方法上使用的。volatile
无法描述同步的处理,它只是一种直接内存的处理,避免了副本的操作 。synchronize
是实现同步的。设计 4 个线程对象,两个线程执行减操作,两个线程执行加操作。
public class Test {
public static void main(String[] args) {
Resource resource = new Resource();
AddThread at = new AddThread(resource);
SubThread st = new SubThread(resource);
new Thread(at, "加法a").start();
new Thread(at, "加法b").start();
new Thread(st, "减法a").start();
new Thread(st, "减法b").start();
}
}
class Resource { // 操作资源
private int num = 0;
private boolean flag = true;
// true 表示可以进行加法 无法减法
public synchronized void add() throws InterruptedException {
if (!this.flag) {
super.wait();
}
Thread.sleep(100);
this.num++;
System.out.println("加法操作" + Thread.currentThread().getName() + " num = " + this.num);
this.flag = false;
super.notifyAll();
}
public synchronized void sub() throws InterruptedException {
if (this.flag) {
super.wait();
}
Thread.sleep(200);
this.num--;
System.out.println("减法操作" + Thread.currentThread().getName() + " num = " + this.num);
this.flag = true;
super.notifyAll();
}
}
class AddThread implements Runnable {
private Resource resource;
public AddThread(Resource resource) {
this.resource = resource;
}
public void run() {
for (int x = 0; x < 50; x++) {
try {
this.resource.add();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class SubThread implements Runnable {
private Resource resource;
public SubThread(Resource resource) {
this.resource = resource;
}
public void run() {
for (int x = 0; x < 50; x++) {
try {
this.resource.sub();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
设计一个生产电脑和搬运电脑的类,要求生产出一台电脑就搬走一台电脑,如果没有新的电脑生产出来,则搬运要等待,如果生产的没有搬走,则要等待搬走后再生产,并统计处生产的电脑的数量。
public class Test {
public static void main(String[] args) {
Resource resource = new Resource();
new Thread(new Producer(resource)).start();
new Thread(new Consumer(resource)).start();
}
}
class Producer implements Runnable {
private Resource resource;
public Producer(Resource resource) {
this.resource = resource;
}
public void run() {
for (int x = 0; x < 50; x++) {
try {
this.resource.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
private Resource resource;
public Consumer(Resource resource) {
this.resource = resource;
}
public void run() {
for (int x = 0; x < 50; x++) {
try {
this.resource.get();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Resource {
private Computer computer;
public synchronized void produce() throws InterruptedException {
if (this.computer != null) {
super.wait();
}
this.computer = new Computer("名字", 1111);
System.out.println("生产" + this.computer);
super.notifyAll();
}
public synchronized void get() throws InterruptedException {
if (this.computer == null) {
super.wait();
}
System.out.println("取走" + this.computer);
this.computer = null;
super.notifyAll();
}
}
class Computer {
private static int count = 0;
private String name;
private double price;
public Computer(String name, double price) {
this.name = name;
this.price = price;
count++;
}
public String toString() {
return "名字" + this.name + "价值 " + this.price + "第" + count + "台";
}
}
竞拍抢答:设置三个抢答线程,同时发出抢答指令,输出抢答结果
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread mt = new MyThread();
FutureTask<String> task = new FutureTask<>(mt);
new Thread(task, "A").start();
new Thread(task, "B").start();
new Thread(task, "C").start();
System.out.println(task.get());
}
}
class MyThread implements Callable<String> {
private boolean flag = false;
public String call() {
synchronized (this) {
if (this.flag == false) {
this.flag = true;
return Thread.currentThread().getName() + " 成功";
} else {
return Thread.currentThread().getName() + " 失败";
}
}
}
}