Java多线程
2023-12-14 17:34:58
多线程
-
程序是指令和数据的有序集合,起本升本没有任何运行的含义,是一个静态的概念
-
进程是执行程序的一次执行过程,他是一个动态的概念,是系统资源分配的单位
-
通常在一个进程中,可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义,线程是cpu调度和执行的单位
线程的创建
三种创建方式
-
继承Thread类(重点)
//创建线程方式1:继承Thread类,重写run,调用start开启线程 public class TestThread1 extends Thread{ @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("-----"); } } public static void main(String[] args) { //创建一个线程对象 TestThread1 testThread1 = new TestThread1(); //调用start方法,开启线程 testThread1.start(); //main线程,主线程 for (int i = 0; i < 20; i++) { System.out.println("主线程"); } } } //两个线程是同时执行的,线程开启后不一定立即执行,按照cpu安排调度
实现图片同步下载
package org.example; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.rmi.Naming; //实现多线程同步下载图片 public class TestThread2 extends Thread{ private String url; private String path; public TestThread2(String url,String name){ this.url =url; this.path =name; } @Override public void run() { WebDownloader webDownloader = new WebDownloader(); webDownloader.downloader(url, path); System.out.println("下载了文件名为:"+path); } public static void main(String[] args) { String url ="https://img-blog.csdnimg.cn/3199ad8ae6974b33953faa7a233a763a.png"; String path = "test.jpg"; TestThread2 t1 = new TestThread2(url, path); TestThread2 t2 = new TestThread2("https://img-blog.csdnimg.cn/cd63b3bdaa6d4c468238922c197bd2f7.png", "2.jpg"); TestThread2 t3 = new TestThread2("https://img-blog.csdnimg.cn/ae7b9b2c89fb4069802660a4d6bbd691.png", "3.jpg"); t1.start(); t2.start(); t3.start(); } } class WebDownloader{ public void downloader(String url, String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); } } }
-
实现Runnable接口(重点)
package org.example; public class TestRunnable1 implements Runnable{ @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("多线程启动"); } } public static void main(String[] args) { TestRunnable1 testRunnable1 = new TestRunnable1(); new Thread(testRunnable1).start(); for (int i = 0; i < 30; i++) { System.out.println("主线程"); } } }
package org.example; //龟兔赛跑 public class Race implements Runnable{ private String winner; @Override public void run() { for (int i = 0; i <=100; i++) { if(Thread.currentThread().getName().equals("兔子") && i %10 ==0){ try { Thread.sleep(1); } catch (InterruptedException e) { throw new RuntimeException(e); } } if(gameOver(i)) break; System.out.println(Thread.currentThread().getName()+"跑了"+i+"步"); gameOver(i); } } private boolean gameOver(int step){ if(winner != null){ return true; }else { if(step == 100){ winner = Thread.currentThread().getName(); System.out.println("winer is " +winner); return true; } } return false; } public static void main(String[] args) { Race race = new Race(); new Thread(race,"兔子").start(); new Thread(race,"乌龟").start(); } }
-
实现Callable接口(了解)
静态代理模式
代理对象可以做额外的事情
真实对象只需要做要做的事情
package org.example;
//静态代理模式:真实对象和代理对象都要实现同一个接口,代理对象要代理真实角色,
public class StaticProxy {
public static void main(String[] args) {
Person person = new Person();
WeddingCompany weddingCompany = new WeddingCompany(person);
weddingCompany.marry();
}
}
interface Marry{
void marry();
}
class Person implements Marry{
@Override
public void marry() {
System.out.println("要结婚了超开心");
}
}
class WeddingCompany implements Marry{
private Marry target;
public WeddingCompany(Marry target){
this.target =target;
}
@Override
public void marry() {
before();
this.target.marry();
after();
}
private void after() {
System.out.println("结婚之后收尾款");
}
private void before() {
System.out.println("结婚前布置现场");
}
}
线程状态
线程停止
- 不退将jdk提供的stop(),destory()方法
- 推荐线程自己停下来
- 金阿姨使用一个标志位进行终止变量
package org.example;
import jdk.internal.org.objectweb.asm.tree.analysis.SourceInterpreter;
public class TestStop implements Runnable{
private boolean flag =true;
@Override
public void run() {
while (flag){
System.out.println("线程在执行");
}
}
public void stop(){
flag = false;
}
public static void main(String[] args) {
TestStop testStop = new TestStop();
new Thread(testStop).start();
for (int i = 0; i < 1000; i++) {
System.out.println(i);
if( i== 900){
testStop.stop();
System.out.println("线程停止了" );
break;
}
}
}
}
线程休眠
sleep(time) 毫秒
存在InterruptedException
sleep可以模拟网络延迟倒计时
每个对象都有锁,sleep不会释放锁
线程礼让
- 礼让线程,让当前正在执行的线程暂停,但不阻塞
- 将线程从运行状态转为就绪状态
- 让cpu重新调度,礼让不一定成功,看cpu心情
package org.example;
public class TestYield {
public static void main(String[] args) {
myYield myYield = new myYield();
new Thread(myYield,"a").start();
new Thread(myYield,"b").start();
}
}
class myYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"线程停止执行");
}
}
join
Join线程合并,待此线程执行完成后,再执行其他线程,其他线程阻塞
package org.example;
public class TestJoin {
public static void main(String[] args) {
MyJoin myJoin = new MyJoin();
Thread thread = new Thread(myJoin);
thread.start();
for (int i = 0; i < 500; i++) {
if(i ==200){
try {
thread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("main"+i);
}
}
}
class MyJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("线程vip来了"+i);
}
}
}
检测线程状态
package org.example;
public class TestStatus {
public static void main(String[] args) {
Thread r = new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
System.out.println("---");
} catch (InterruptedException e) {
}
}
});
System.out.println(r.getState());
r.start();
System.out.println(r.getState());
}
}
线程的优先级
先设置优先级在启动,大的先执行,但是还是由cpu决定
package org.example;
public class TestPriority {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+" "+Thread.currentThread().getPriority());
Thread t1 = new Thread(new myPriority());
Thread t2 = new Thread(new myPriority());
Thread t3 = new Thread(new myPriority());
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(8);
t3.start();
}
}
class myPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" "+Thread.currentThread().getPriority());
}
}
守护线程
- 线程分为用户线程和守护线程
- 虚拟机确保用户线程执行完毕
- 虚拟机不用等待守护线程执行完毕
package org.example;
public class TestDaemon {
public static void main(String[] args) {
god god = new god();
You you = new You();
Thread thread = new Thread(god);
//设置守护县城
thread.setDaemon(true);
thread.start();
new Thread(you).start();
}
}
class god implements Runnable{
@Override
public void run() {
while (true){
System.out.println("上帝保佑着你");
}
}
}
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("happy everyDay");
}
System.out.println("goodBye world");
}
}
线程同步
多个线程操作同一个资源
不安全
package syn;
import sun.rmi.runtime.NewThreadAction;
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket,"1").start();
new Thread(buyTicket,"2").start();
new Thread(buyTicket,"3").start();
new Thread(buyTicket,"4").start();
}
}
class BuyTicket implements Runnable{
private int ticket =10;
private boolean flag = true;
@Override
public void run() {
while (flag){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
buy();
}
}
private void buy(){
if(ticket <= 0) {
stop();
return;
}
System.out.println(Thread.currentThread().getName()+"拿到第"+ticket--+"张票");
}
public void stop(){
flag =false;
}
}
线程同步
使用synchronized
synchronized方法控制对"对象的访问",每个对象对应一把锁,每个sync方法都必须获得调用该方法的对象的锁才能执行,否则会线程阻塞
方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行
package syn;
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket,"1").start();
new Thread(buyTicket,"2").start();
new Thread(buyTicket,"3").start();
new Thread(buyTicket,"4").start();
}
}
class BuyTicket implements Runnable{
private int ticket =10;
private boolean flag = true;
@Override
public void run() {
while (flag){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
buy();
}
}
private synchronized void buy(){
if(ticket <= 0) {
stop();
return;
}
System.out.println(Thread.currentThread().getName()+"拿到第"+ticket--+"张票");
}
public void stop(){
flag =false;
}
}
同步块
sycn(obj){}
obj称之为同步监视器
- obj可以是任何对象,但是推荐使用共享资源作为同步监视器
- 同步方法中无需指定同步监视器,因为同步方法的同步器就是thism就是这个对象本身,或者是class
同步监视器执行过程
- 第一个线程访问,锁定同步监视器,执行方法
- 第二个线程访问,发现同步监视器被锁定,无法访问
- 第一个线程访问完毕,解锁同步监视器
- 第二个线程访问,发现没有被锁定,锁定监视器,执行代码.
package syn;
import java.util.ArrayList;
public class UnSafeList {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(list.size());
}
}
juc下的线程安全集合
package syn;
import java.util.concurrent.CopyOnWriteArrayList;
public class TestJUC {
public static void main(String[] args) {
//测试juc安全数组
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
for (int i = 0; i < 1000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(list.size());
}
}
死锁
多个线程各自占有一些共享资源,并且互相等待其他线程占有的支援才能运行,而导致两个或多个线程都在等待对方释放资源,都停止执行的 场景,某个同步块同时拥有"两个以上对象的锁"时就有可能会发生死锁问题.
package syn;
//死锁:多个线程互相占有对方的支援,形成僵持
public class Lock {
public static void main(String[] args) {
MakeUp m1= new MakeUp(0, "1");
MakeUp m2= new MakeUp(0, "2");
m1.start();
m2.start();
}
}
//口红
class Lipstick{}
//镜子
class Mirror{}
class MakeUp extends Thread{
static Lipstick lipstick =new Lipstick();
static Mirror mirror = new Mirror();
int choice;
String girlName;
MakeUp(int choice,String girlName){
this.choice = choice;
this.girlName = girlName;
}
@Override
public void run() {
//化妆
try {
makeup();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
//互相拿到对方的锁
private void makeup() throws InterruptedException {
if(choice == 0){
synchronized (lipstick){
System.out.println(this.girlName+"获得口红的锁");
Thread.sleep(5000);
synchronized (mirror){
System.out.println("获得镜子的锁");
}
}
}else {
synchronized (mirror){
System.out.println(this.girlName+"获得口红的锁");
Thread.sleep(4000);
synchronized (lipstick){
System.out.println("获得镜子的锁");
}
}
}
}
}
Lock
package gaoji;
import java.util.concurrent.locks.ReentrantLock;
//测试lock
public class TestLock {
public static void main(String[] args) {
testLock2 t2 = new testLock2();
new Thread(t2).start();
new Thread(t2).start();
new Thread(t2).start();
}
}
class testLock2 implements Runnable{
int tickNum =10;
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true){
try {
//放到try里面
lock.lock();
if(tickNum >0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(tickNum--);
}else {
break;
}
}finally {
//一般写到finally
lock.unlock();
}
}
}
}
线程协作
Java提供了几个方法解决线程之间的通信问题
package gaoji;
//测试生产者消费者模型
public class TestPC {
public static void main(String[] args) {
SyncContainer syncContainer = new SyncContainer();
Producer producer = new Producer(syncContainer);
Consumer consumer = new Consumer(syncContainer);
producer.start();
consumer.start();
}
}
class Producer extends Thread{
SyncContainer container;
public Producer(SyncContainer container){
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
container.push(new Chicken(i));
System.out.println("生产了"+i+"只鸡");
}
}
}
class Consumer extends Thread{
SyncContainer container;
public Consumer(SyncContainer container){
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了第"+container.pop());
}
}
}
class Chicken{
int id;
public Chicken(int id) {
this.id = id;
}
@Override
public String toString() {
return "Chicken{" +
"id=" + id +
'}';
}
}
//缓冲区
class SyncContainer{
Chicken[] chickens = new Chicken[10];
//容器计数器
int cnt = 0;
//生产者放入产品
public synchronized void push(Chicken product) {
if (cnt == 10) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
chickens[cnt] = product;
cnt++;
this.notifyAll();
}
public synchronized Chicken pop() {
if (cnt == 0) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
cnt--;
Chicken product = chickens[cnt];
this.notifyAll();
return product;
}
}
线程池
提前创建好多个线程,放入线程池,使用时直接获取,使用完放回池中
package gaoji;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPool {
public static void main(String[] args) {
//创建线程池,参数为大小
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new myThread());
executorService.execute(new myThread());
executorService.execute(new myThread());
executorService.execute(new myThread());
}
}
class myThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
roduct;
}
}
## 线程池
提前创建好多个线程,放入线程池,使用时直接获取,使用完放回池中
[外链图片转存中...(img-4V6tDQBC-1702542956181)]
[外链图片转存中...(img-9qAWm6xK-1702542956181)]
```java
package gaoji;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPool {
public static void main(String[] args) {
//创建线程池,参数为大小
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new myThread());
executorService.execute(new myThread());
executorService.execute(new myThread());
executorService.execute(new myThread());
}
}
class myThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
文章来源:https://blog.csdn.net/m0_74347016/article/details/134999054
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!