多线程在我们日常工作中相对来说属于比较难缠的技术,根据业务逻辑的不同,线程与线程间的通信都会比较繁琐,至于多线程的基础知识这里不多做赘述,网上有很多,今天自己用线程做了几个非常简单的小习题,代码贴出来,因为对并发包还没有怎么看,这些都是基于synchronized关键字去实现的,多线程我也不是很熟,有什么不对的地方,各位大佬指正.
首先是线程的几种实现方式:
package com.multithreading;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* @program: study
* @description: 多线程学习
* @author: Elias.Guo
* @create: 2020-06-08 13:33
**/
public class Multithreading {
//全局锁对象
Object lock =new Object();
//线程创建-实现Runnable接口
class Thread2 implements Runnable {
private String name;
public Thread2(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
synchronized (lock){
System.out.println("线程:" + name + "输出:" + i);
try{
lock.notify();
lock.wait();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
}
//线程创建-继承Thread类
class Thread3 extends Thread {
private String name;
public Thread3(String name) {
this.name = name;
}
char[] chars = new char[]{'A', 'B', 'C', 'D', 'E'};
@Override
public void run() {
for (int i = 0; i < chars.length; i++) {
synchronized (lock){
System.out.println("线程:" + name + "输出:" + chars[i]);
try {
lock.notify();
lock.wait();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
}
//线程创建-实现Callable接口(有返回值)
class Thread4 implements Callable {
@Override
public Object call() throws Exception {
List<String> list =new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
return list;
}
}
@Test
public void test1() throws ExecutionException, InterruptedException {
//传统创建线程
//new Thread(new Thread2("B")).start();
//new Thread(new Thread3("C")).start();
//线程池创建线程
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new Thread2("B"));
executorService.execute(new Thread3("C"));
// Future 接收类型
Future<List<String>> submit =executorService.submit(new Thread4());
//get()方法获取返回值
List<String> list =submit.get();
list.forEach(s -> System.out.println(s));
}
}
运行结果如下:
"C:\Program Files\Java\jdk1.8.0_171\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\IDEA\IntelliJ IDEA Community Edition 2020.1\lib\idea_rt.jar=62030:D:\IDEA\IntelliJ IDEA Community Edition 2020.1\bin" -Dfile.encoding=UTF-8 -classpath "D:\IDEA\IntelliJ IDEA Community Edition 2020.1\lib\idea_rt.jar;D:\IDEA\IntelliJ IDEA Community Edition 2020.1\plugins\junit\lib\junit5-rt.jar;D:\IDEA\IntelliJ IDEA Community Edition 2020.1\plugins\junit\lib\junit-rt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\rt.jar;D:\workspaces\study\out\production\study;D:\RepMaven\junit\junit\4.12\junit-4.12.jar;D:\RepMaven\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.multithreading.Multithreading,test1
线程:B输出:1
线程:C输出:A
线程:B输出:2
线程:C输出:B
线程:B输出:3
线程:C输出:C
线程:B输出:4
线程:C输出:D
线程:B输出:5
线程:C输出:E
1
2
3
4
5
Process finished with exit code 0
下面这个练习,是做线程间的通信:
package com.multithreading;
import org.junit.Test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @program: study
* @description: 多线程学习第二天
* @author: Elias.Guo
* @create: 2020-06-09 15:05
**/
public class Multithreading2 {
/**
* 练习题:定义三个线程,能够轮换输出12Aa,34Bb,56Cc....
*/
//定义全局锁,保证线程获取到的是同一个锁
private static final Object lock = new Object();
//定义一个全局标识
private static int flag = 1;
static class Thread1 implements Runnable {
private String name;
public Thread1(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 1; i < 52; i += 2) {
synchronized (lock) {
try {
while (flag != 1) {
lock.wait();
}
System.out.print( i);
System.out.print((i + 1));
flag = 2;
lock.notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
static class Thread2 implements Runnable {
private String name;
public Thread2(String name) {
this.name = name;
}
char[] chars = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'
, 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
@Override
public void run() {
for (int i = 0; i < chars.length; i++) {
synchronized (lock) {
try {
while (flag != 2) {
lock.wait();
}
System.out.print(chars[i]);
flag = 3;
lock.notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
static class Thread3 implements Runnable {
private String name;
public Thread3(String name) {
this.name = name;
}
char[] chars = new char[]{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'
, 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
@Override
public void run() {
for (int i = 0; i < chars.length; i++) {
synchronized (lock) {
try {
while (flag != 3) {
lock.wait();
}
System.out.println( chars[i]);
flag = 1;
lock.notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String args[]) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new Thread1("A"));
executorService.execute(new Thread2("B"));
executorService.execute(new Thread3("C"));
// new Thread(new Thread1("A")).start();
// new Thread(new Thread2("B")).start();
// new Thread(new Thread3("C")).start();
}
}
运行结果如下
"C:\Program Files\Java\jdk1.8.0_171\bin\java.exe" "-javaagent:D:\IDEA\IntelliJ IDEA Community Edition 2020.1\lib\idea_rt.jar=62084:D:\IDEA\IntelliJ IDEA Community Edition 2020.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_171\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\rt.jar;D:\workspaces\study\out\production\study;D:\RepMaven\junit\junit\4.12\junit-4.12.jar;D:\RepMaven\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" com.multithreading.Multithreading2
12Aa
34Bb
56Cc
78Dd
910Ee
1112Ff
1314Gg
1516Hh
1718Ii
1920Jj
2122Kk
2324Ll
2526Mm
2728Nn
2930Oo
3132Pp
3334Qq
3536Rr
3738Ss
3940Tt
4142Uu
4344Vv
4546Ww
4748Xx
4950Yy
5152Zz
下面是模仿票务系统:
package com.multithreading;
/**
* @program: study
* @description:
* @author: Elias.Guo
* @create: 2020-06-09 16:44
**/
public class Multithreading4 {
/**还是票务系统 用共享变量的方式实现*/
private static volatile int ticket=100;
private static Object lock =new Object();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while (true){
synchronized (lock){
if(ticket>0){
ticket--;
System.out.println(Thread.currentThread().getName()+"卖出了一张票,还剩:"+ticket+"张票");
}else{
System.out.println("票已卖光!");
break;
}
try {
Thread.sleep(500);
}catch (Exception e){
e.printStackTrace();
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
synchronized (lock){
if(ticket>0){
ticket--;
System.out.println(Thread.currentThread().getName()+"卖出了一张票,还剩:"+ticket+"张票");
}else{
System.out.println("票已卖光!");
break;
}
try {
Thread.sleep(500);
}catch (Exception e){
e.printStackTrace();
}
}
}
}
}).start();
}
}
输出结果如下,只截取一小段:
Thread-0卖出了一张票,还剩:99张票
Thread-0卖出了一张票,还剩:98张票
Thread-0卖出了一张票,还剩:97张票
Thread-0卖出了一张票,还剩:96张票
Thread-0卖出了一张票,还剩:95张票
Thread-0卖出了一张票,还剩:94张票
Thread-0卖出了一张票,还剩:93张票
Thread-0卖出了一张票,还剩:92张票
Thread-0卖出了一张票,还剩:91张票
Thread-0卖出了一张票,还剩:90张票
Thread-0卖出了一张票,还剩:89张票
Thread-0卖出了一张票,还剩:88张票
Thread-0卖出了一张票,还剩:87张票
Thread-0卖出了一张票,还剩:86张票
Thread-0卖出了一张票,还剩:85张票
Thread-0卖出了一张票,还剩:84张票
Thread-0卖出了一张票,还剩:83张票
Thread-0卖出了一张票,还剩:82张票
Thread-0卖出了一张票,还剩:81张票
Thread-0卖出了一张票,还剩:80张票
Thread-1卖出了一张票,还剩:79张票
Thread-1卖出了一张票,还剩:78张票
Thread-1卖出了一张票,还剩:77张票
Thread-1卖出了一张票,还剩:76张票
Thread-1卖出了一张票,还剩:75张票
Thread-1卖出了一张票,还剩:74张票
Thread-1卖出了一张票,还剩:73张票
Thread-1卖出了一张票,还剩:72张票
Thread-1卖出了一张票,还剩:71张票
Thread-1卖出了一张票,还剩:70张票
Thread-1卖出了一张票,还剩:69张票
Thread-1卖出了一张票,还剩:68张票
多线程的并发包,包含读写锁,可以实现高并发情况下的读写分离,用于构建高性能的缓存系统可能会更方便一些,这个我回头会看一下相关的文档学习一下,继续更新.