Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Java multithreaded programming

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article focuses on "how to use Java multithreaded programming". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to use Java multithreaded programming.

Process and Thread

A program is an ordered collection of instructions and data, which has no meaning to run and is a static concept.

A process is an execution process of an execution program. It is a dynamic concept and a unit of system resource allocation.

A process can contain several threads, which are the units of CPU scheduling and execution

Thread creation

Three creation methods

Inherit Thread class / / create thread method 1: inherit Thread class, override the run () method, call start to start the main thread public class TestThread01 extends Thread {@ Override public void run () {/ / run method thread body for (int I = 0; I)

< 2000; i++) { System.out.println("我在看代码-----" + i); } } public static void main(String[] args) { //main线程,主线程 //创建一个线程对象 TestThread01 testThread01 = new TestThread01(); //调用start方法开启多线程,子线程调用run方法,主线程和子线程并行交替执行 testThread01.start(); //testThread01.run(); //主线程调用run方法,只有主线程一条执行路径 for (int i = 0; i < 2000; i++) { System.out.println("Im" + i); } }} 总结:注意,线程开启不一定立即执行,由CPU调度处理 子类继承Thread类,具备多线程能力、 启动线程:子类对象.start() 不推荐使用:避免OOP单继承局限性 小练习 import org.apache.commons.io.FileUtils;import java.io.File;import java.io.IOException;import java.net.URL;//练习Thread,实现多线程同步下载图片public class TestThread02 extends Thread{ private String url; private String name; public TestThread02(String url, String name) { this.url = url; this.name = name; } @Override public void run() { WebDownloader webDownloader = new WebDownloader(); webDownloader.downloadr(url, name); System.out.println("下载了:" + name); } public static void main(String[] args) { TestThread02 t1 = new TestThread02("https://cache.yisu.com/upload/information/20211214/112/75486.png?…3dlaXhpbl80NDE3NjM5Mw==,size_16,color_FFFFFF,t_70", "1.png"); TestThread02 t2 = new TestThread02("https://cache.yisu.com/upload/information/20211214/112/75487.png", "2.png"); TestThread02 t3 = new TestThread02("https://cache.yisu.com/upload/information/20211214/112/75486.png?…3dlaXhpbl80NDE3NjM5Mw==,size_16,color_FFFFFF,t_70", "3.png"); t1.start(); t2.start(); t3.start(); }}//下载器class WebDownloader{ public void downloadr(String url, String name){ try { FileUtils.copyURLToFile(new URL(url), new File(name)); } catch (IOException e) { e.printStackTrace(); System.out.println("IO异常, downloader出现问题"); } }}实现Runnable//创建线程方式二:实现Runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法public class TestThread03 implements Runnable{ @Override public void run() { //run方法线程体 for (int i = 0; i < 2000; i++) { System.out.println("我在看代码-----" + i); } } public static void main(String[] args) { //创建runnable 接口的实现类对象 TestThread03 testThread03 = new TestThread03(); //创建线程对象,通过线程对象来开启线程,代理// Thread thread = new Thread(testThread03);// thread.start(); new Thread(testThread03).start(); for (int i = 0; i < 1000; i++) { System.out.println("Im" + i); } }} 总结: 实现接口Runnable具备多线程能力 启动线程:传入目标对象+Thread对象.start() 推荐使用:避免单继承局限性,灵活方便,方便同一个对象被线程使用 出现的问题 多个线程操作操作同一个资源的情况下,线程不安全,数据紊乱 //多个线程同时操作同一个对象//买火车票的例子//发现问题:多个线程操作操作同一个资源的情况下,线程不安全,数据紊乱public class TestThread04 implements Runnable { //票数 private int ticketNums = 10; @Override public void run() { while (true) { if (ticketNums { System.out.println("I like lambda5"); }; like.lambda(); }}//1、定义一个函数式接口----必须有interface ILike { void lambda();}//2、实现类class Like implements ILike { @Override public void lambda() { System.out.println("I like lambda"); }} 对于lambda表达式的简化 public class TestLambda02 { public static void main(String[] args) { //标准格式// ILove love = (int a)->

{/ / System.out.println ("ILove you" + a); / /}; / / simplify 1 remove parameter types, and several different types of parameters can also be removed directly ILove love = (a)-> {System.out.println ("I love you" + a);} / / Simplification 2 remove parentheses-> only single parameter love = a-> {System.out.println ("I love you" + a);}; / / Simplification 3 remove curly braces-> only if the lambda expression has a line love = a-> System.out.println ("I love you" + a); love.love / / using lambda expressions is only applicable to functional interfaces (there is only one functional interface in the interface)}} interface ILove {void love (int a) } static proxy / / static proxy mode: / / both real objects and proxy objects have to implement the same interface / / proxy objects should proxy real roles / / benefits: / / proxy objects can do a lot of things that real objects cannot / / real objects focus on doing their own things public class StaticProxy {public static void main (String [] args) {You you = new You () New Thread (()-> System.out.println ("I Love You")). Start (); new WeddingCompany (new You ()). HappyMarry ();}} interface Marry {void HappyMarry ();} / Real object class You implements Marry {@ Override public void HappyMarry () {System.out.println ("Happy");}} / / Agent class WeddingCompany implements Marry {/ / Agent who-> Real Target character private Marry target; public WeddingCompany (Marry target) {this.target = target } @ Override public void HappyMarry () {before (); this.target.HappyMarry (); after ();} private void after () {System.out.println (after);} private void before () {System.out.println (front) }} Thread state method states that setPriority (int newPriority) changes the priority of a thread static void sleep (long millis) makes the currently executing thread hibernate within a specified number of milliseconds void join () waits for the thread to terminate static void yield () pauses the currently executing thread object and executes other threads void interrupt () interrupts the thread, do not boolean isAlive () to test whether the thread is in an active state and terminates

The stop () and destroy () methods provided by JDK are not recommended.

It is recommended that the thread stop itself.

It is recommended to use a flag bit to terminate the variable. When flag = false, the thread is terminated.

/ / Test stop//1, recommend thread to stop normally-> use times, do not recommend endless loop / / 2, recommend using flag bit-> set a flag bit / / 3, do not use outdated methods such as stop or destroy or jdk do not recommend public class TestStop implements Runnable {/ / 1, set a flag bit private boolean flag = true; @ Override public void run () {int I = 0 While (flag) {System.out.println ("run-thread" + iTunes +);}} / / 2. Set a public method to stop the thread and convert the flag bit public void stop () {this.flag = false;} public static void main (String [] args) throws InterruptedException {TestStop testStop = new TestStop (); new Thread (testStop). Start () For (int I = 0; I

< 1000; i++) { Thread.sleep(1); if (i == 900) { testStop.stop(); System.out.println("Stop"); break; } } }}线程休眠 sleep(时间) 指定当前线程阻塞的毫秒数 sleep存在异常InterruptedException sleep时间达到后进入就绪状态 sleep可以模拟网络延时(放大问题的发生性),倒计时等 每一个对象都有一个锁,sleep不会释放锁 import java.text.SimpleDateFormat;import java.util.Date;public class TestSleep2 { //模拟倒计时 public static void tenDown(){ int num = 10; while (num >

0) {try {Thread.sleep (1000);} catch (InterruptedException e) {e.printStackTrace ();} System.out.println (num--);}} public static void main (String [] args) {/ / print current time Date startTime = new Date (System.currentTimeMillis ()) / / get while (true) {try {Thread.sleep (1000); System.out.println (new SimpleDateFormat ("HH:MM:SS") .format (startTime)); startTime = new Date (System.currentTimeMillis ()); / / Update time} catch (InterruptedException e) {e.printStackTrace () } Thread comity

Comity thread to stop the currently executing thread without blocking

Change a thread from a running state to a ready state

Let CPU reschedule, comity may not be successful, depending on CPU's mood.

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 start"); Thread.yield () System.out.println (Thread.currentThread (). GetName () + "thread stop");}} JOIN

JOIN merges threads and executes other threads after this thread has finished executing. Other threads block

You can imagine jumping the queue.

/ / public class TestJoin implements Runnable {@ Override public void run () {try {Thread.sleep (20);} catch (InterruptedException e) {e.printStackTrace ();} for (int I = 0; I)

< 100; i++) { System.out.println("VIP" + i); } } public static void main(String[] args) { TestJoin testJoin = new TestJoin(); Thread thread = new Thread(testJoin); thread.start(); for (int i = 0; i < 1000; i++) { if (i == 200) { try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("main" + i); } }}线程状态观测 线程状态。线程可以处于以下状态之一: NEW 尚未启动的线程处于此状态。 RUNNABLE 在Java虚拟机中执行的线程处于此状态。 BLOCKED 被阻塞等待监视器锁定的线程处于此状态。 WAITING 无限期等待另一个线程执行特定操作的线程处于此状态。 TIMED_WAITING 正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。 TERMINATED 已退出的线程处于此状态。 //观测测试线程的状态public class TestStatus { public static void main(String[] args) { Thread thread = new Thread(() ->

{for (int I = 0; I)

< 5; i++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); } System.out.println("/////////////"); }); //观察状态 Thread.State state = thread.getState(); System.out.println(state); //观察启动后 thread.start(); state = thread.getState(); System.out.println(state); while (state != Thread.State.TERMINATED) { //只要线程不终止,就一直输出状态 try { Thread.sleep(100); state = thread.getState(); System.out.println(state); } catch (InterruptedException e) { e.printStackTrace(); } } }}线程的优先级 Java提供一个线程调度器来监控程序中启动后进入就绪态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行 线程的优先级用数字表示,范围从1~10 Thread.MIN_PRIORITY = 1; Thread.MAX_PRIORITY = 10; Thread.NORM_PRIORITY = 5; 使用以下方法改变或者获取优先级 getPriority setPriority 优先级低只是意味着获得调度的概率低,并不是优先级低的就不会调用了,这都是看CPU的调度 public class TestPriority extends Thread { public static void main(String[] args) { System.out.println(Thread.currentThread().getName() + "====>

"+ Thread.currentThread () .getPriority (); MyPriority myPriority = new MyPriority (); Thread T1 = new Thread (myPriority); Thread T2 = new Thread (myPriority); Thread T3 = new Thread (myPriority); Thread T4 = new Thread (myPriority); Thread T5 = new Thread (myPriority); t1.start (); t2.setPriority (1); t2.start (); t3.setPriority (4) T3.start (); t4.setPriority (Thread.MAX_PRIORITY); t4.start (); t5.setPriority (8); t5.start ();}} class MyPriority implements Runnable {@ Override public void run () {System.out.println (Thread.currentThread () .getName () + "= >" + Thread.currentThread () .getPriority ());}} daemon (daemon) thread

Threads are divided into user threads and daemon threads

The JVM virtual machine must ensure that the user thread is finished

The JVM virtual machine does not have to wait for the daemon thread to finish execution

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); / / default false indicates user thread, normal thread is user thread thread.start (); new Thread (you). Start () }} / / God class God implements Runnable {@ Override public void run () {while (true) {System.out.println ("god");}} / / you class You implements Runnable {@ Override public void run () {for (int I = 0; I < 36500; iTunes +) {System.out.println ("Happy") } System.out.println ("Goodbye world");}} synchronization (synchronized)

Synchronized

Since we can propose the private keyword to ensure that the data object can only be accessed by the method, we only need to propose a mechanism for the method, which is the synchronized keyword, which includes two uses: the synchronized method and the synchronized block.

Public synchronized void method () {}

The synchronized method controls access to the "object". Each object corresponds to a lock. Each synchronized method must obtain the lock of the object calling the method before it can be executed, otherwise the thread will block. Once the method is executed, the lock will be monopolized, and the lock will not be released until the method returns, and the later blocked thread can acquire the lock and continue to execute.

Defect: if a large method is declared as synchronized, it will affect efficiency

Synchronization method

The synchronized method controls access to member variables or class property objects, each of which corresponds to a lock. It is written as follows:

Public synchronized void test () {/ /. }

If you are decorating a specific object: the lock is an object

If the modifier is a member method: the lock is this

If you are decorating a static method: this is the object that locks .class.

Each synchronized method must acquire a lock on the object of the method before it can be executed, otherwise the thread to which it belongs blocks, and once the method is executed, the lock is monopolized until the lock is released when the method returns.

Original program:

Public class Checkout {public static void main (String [] args) {Account account = new Account (200000, "gift money"); Drawing you = new Drawing (account, 80000, "you"); Drawing wife = new Drawing (account, 140000, "your wife"); you.start (); wife.start ();} class Account {int money; String name Public Account (int money, String name) {this.money = money; this.name = name;}} class Drawing extends Thread {Account account; int outMoney; int outTotal; public Drawing (Account account, int outMoney, String name) {super (name); this.account = account; this.outMoney = outMoney;} @ Override public void run () {test () } public void test () {if (account.money < outMoney) {System.out.println ("insufficient balance"); return;} try {Thread.sleep (200);} catch (InterruptedException e) {e.printStackTrace ();} account.money-= outMoney; outTotal + = outMoney

Obviously, the above code will have a negative number, but we don't want it to have a negative number.

@ Overridepublic void run () {} public synchronized void test () {}

However, you will still find that there is a negative number and the lock fails.

Analysis:

We think that the object modification is made in the test method, so it would be fine to lock it, but for this class, this cash machine, the Testt member method, so the locked object is actually this, that is, the cash machine (Drawing).

But our original intention is that the resource that the thread locks is the Account object, not the ATM object.

Synchronization block

In addition to methods, synchronized can also modify blocks, called synchronous blocks.

Synchronized modifies synchronous blocks by:

Synchonized (obj) {}

The obj can be any object, but if it is used, it must be set to the shared resource, and this obj is called the synchronization monitor. The role of the synchronization monitor is to determine whether the monitor is locked (accessible) and thus whether it can execute the code in it.

The curly braces of Java have the following contents:

The block in the method: local fast. Solve the problem of variable scope and release memory quickly (for example, there is a for loop in the method and the variables in it)

Block of class layer: building block. The initialization information is the same as the construction method

Static block of class layer: static building block. The earliest load is not the information of the object, but the information of the class.

The synchronization block in the method: monitor object.

The fourth is the synchronized block of our current study.

Note: if it is in a synchronization method, it is not necessary to specify a synchronization monitor, because the monitor of the synchronization method is already this or .class

Use the synchronization block to modify the ATM problem:

Public void test () {synchronized (account) {}}

That is, add the monitor to the account and lock the object so that the result is correct.

This practice is not efficient, because although the account is locked, it has to go through the whole process every time, and there are a lot of contents in the method body. In addition, every time you lock it or not, it is a consumption of performance. Even if you do nothing, it is also a consumption.

In fact, we can add another judgment on the outside of the lock, then there is no need for the locking process.

Public void test () {if (account.money = = 0) {return;} synchronized (account) {}}

This kind of code can often greatly improve the efficiency when the concurrency is very high.

problem

The synchronized block is too small to lock, the security is too low, and the locking method is too large, which will reduce the efficiency, so we should pay attention to the control range.

At this point, I believe you have a deeper understanding of "how to use Java multithreaded programming". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report