本篇对java中的多线程进行总结,对线程的执行方式:串行、并发进行讲解,以及线程池、同步异步还有一些常用的操作进行了总结,最后通过不同客户购买车票进行了多线程的练习;整体上比较精简,代码可以直接粘贴到idea中执行,方便理解和掌握;
第一篇:线程的基础语法
package java_duoxiancheng;
//TODO 线程:java程序在运行过程中会默认产生一个进程;这个进程会有一个主线程;代码都在这个主线程中进行;
//TODO 线程执行方式:串行、并发;
//串行:多个线程连接成串,然后按照顺序执行
//并发:多个线程独立,谁抢到了CPU的执行权,谁就能执行;
public class java_47 {
public static void main(String[] args) throws InterruptedException {
//Thread是线程类;
//currentThread()方法是获取当前正在运行的线程
//main方法运行在main线程中
//首先对于main线程来说,是一直执行的,相对于其他新建的线程是先执行的;
System.out.println(Thread.currentThread().getName());
MyThread1 t1=new MyThread1();
MyThread2 t2=new MyThread2();
t1.start();
t2.start();
//将线程连接成串:如果没将线程连接成串,先输出主线程执行完毕,因为主线程是先执行的,对于t1和t2来说,谁先拿到cpu执行权不一定,现在连接成串后,t1在t2的前面,
t1.join();
t2.join();
System.out.println("主线程执行完毕!");
}
}
class MyThread1 extends Thread{
//重写运行指令:
@Override
public void run() {//线程执行的内容,这个方法执行结束后,线程就终止了;
System.out.println("MyThread1"+ Thread.currentThread().getName());
}
}
class MyThread2 extends Thread{
public void run(){
System.out.println("MyThread2"+Thread.currentThread().getName());
}
}
第二篇:创建线程的方式
package java_duoxiancheng;
//TODO 之前的新建一个线程就要新建一个class类,但是不想这样,因此采用通用的方法来创建线程并执行:
public class java_49 {
public static void main(String[] args) {
//以下方式不需要一个类一个类的去创建:
Thread t1=new Thread(()->{
System.out.println("线程1执行");
});
t1.start();
Thread t2=new Thread(()->{
System.out.println("线程2执行");
});
t2.start();
//还有一种方式:传递实现了Runnable接口的类的对象,一般使用匿名类;
Thread t3=new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程执行!");
}
});
t3.start();
}
}
第三篇:线程池
package java_duoxiancheng;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//TODO 线程池:所谓的线程池也就是线程对象的容器;可以根据需要,在启动时,创建一个或者多个线程对象;
// java中有四种常见的线程池;
public class java_50 {
public static void main(String[] args) {
//1.创建固定数量的线程对象; ExecutorService是线程服务对象;
// ExecutorService executorService = Executors.newFixedThreadPool(3);
// //上方创建了三个线程对象,总共三个线程;但是如果有四个事务需要做的时候,那么第四个事务就会出现阻塞状态,需要等到其中一个线程处理完,然后再处理第四个事务,如下:可以看到有的线程重复执行;
// for(int i=0;i<5;i++){
// executorService.submit(new Runnable() {
// @Override
// public void run() {
// System.out.println(Thread.currentThread().getName());
// }
// });
// }
//2.根据需求动态创建线程对象:
//此处创建了五个线程,因为for循环中有五次;但是如果有for循环20次的话,会发现并没有创建20个线程,有重复使用的,所以在线程执行结束后,会再进行处理继续执行;
// ExecutorService executorService = Executors.newCachedThreadPool();
// for(int i=0;i<20;i++){
// executorService.submit(new Runnable() {
// @Override
// public void run() {
// System.out.println(Thread.currentThread().getName());
// }
// });
// }
//3.单一线程:如果一些工作是顺序执行的,此时可以用单一线程;
// ExecutorService executorService = Executors.newSingleThreadExecutor();
// for(int i=0;i<20;i++){
// executorService.submit(new Runnable() {
// @Override
// public void run() {
// System.out.println(Thread.currentThread().getName());
// }
// });
// }
//4.
}
}
第四篇:同步异步
package java_duoxiancheng;
//TODO 同步:对于异步来说,就是各个线程互不关联,各自执行各自的;对于同步来说,线程之间就有了关联,
// 一个执行完之后另一个才能执行,之前演示了用join方法来实现,其实有更常用的方法:synchronized关键字
public class java_51 {
public static void main(String[] args) {
//TODO synchronized同步关键字:当多个线程来访问同步方法时,只能有一个线程访问;还可以修饰代码块,称之为同步代码块;
per per = new per();
Thread t1 = new Thread(per);
Thread t2 = new Thread(per);
Thread t3 = new Thread(per);
t1.start();
t2.start();
t3.start();
}
}
class per implements Runnable {
int ticket = 10;
final String a = "";//任意定义的锁对象,只要保证唯一不变即可
@Override
public void run() {
while (ticket>0) {
synchronized (a) {//同步代码块,a是锁对象
if (ticket > 0) {
try {
Thread.sleep(1000);//sleep让程序休眠,加大出现问题的概率,方便定位问题,使用时会有异常try..catch即可
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
ticket--;
}
}
}
}
}
第五篇:线程安全问题
package java_duoxiancheng;
//TODO 线程安全问题:
public class java_52 {
public static void main(String[] args) {
User user=new User();
Thread t1=new Thread(()->{
user.name="zhangsan";
try {
//注意由于这一秒钟的休眠,所以其他线程可能会执行,因此t2中将相同的对象的name属性改为lisi,
// 这个时候休眠结束后,都打印总会都显示lisi,因为在休眠过程中t2已经将name属性更改了,所以竞争同一个对象这样就会出现线程安全问题;如果没有这个休眠的话,就会出现zhangsan lisi
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(user.name);
});
Thread t2=new Thread(()->{
user.name="lisi";
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(user.name);
});
t1.start();
t2.start();
System.out.println("主线程执行完毕!");
}
}
class User{
String name;
}