이 글에서는 동시에 여러 스레드를 실행할 수 있는 관련 내용을 주로 소개하는 java에 대한 관련 지식을 제공합니다. 예: Thunder를 사용하여 동시에 여러 파일을 다운로드할 수 있습니다. 모두에게 도움이 되기를 바랍니다.
추천 학습: "java 비디오 튜토리얼"
1. 프로그램: 특정 작업을 완료하기 위해 특정 언어로 작성된 지침 세트입니다. 간단히 말하면: 는 우리가 작성하는 코드입니다
. 就是我们写的代码
。
2、进程:是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为 该进程分配内存空间。当我们使用迅雷,又启动了一个进程,操作系统将为迅雷分配新的内存空间。
进程是程序的一次执行过程,或是正在运行的一个程序。是动态过程:有它自身的产生、存在和消亡的过程。
3、线程:是进程创建的,是进程的实体,一个进程可以有多个线程
,例如使用迅雷下载文件,迅雷相当于进程,下载的文件相当于线程。
4、单线程:同一时刻,只允许执行一个线程
。
5、多线程:同一时刻,可以执行多个线程
。例如:使用迅雷可以同时下载多个文件。
6、并发:同一时刻,多个任务交替进行
。单核CPU实现的多任务就是并发。
7、并行:同一时刻,多个任务同时进行
。多核CPU可以实现并行,当任务较多时,并发和并行有可能同时发生。
创建线程有两种方法:
1、继承Thread
类,重写run
方法。
2、实现Runnable
接口,重写run
方法。
注意:Thread
类实现了Runnable
接口。
public class Thread01 { public static void main(String[] args) throws InterruptedException { Cat cat = new Cat(); cat.start(); System.out.println("主线程" + Thread.currentThread().getName()); for (int i = 1; i <p>1、在继承<code>Thread</code>类,重写了<code>run()</code>方法后,在<code>main</code>方法中需要创建对象,并调用<code>start()</code>方法,启动线程。</p><p>2、使用<code>start()</code>方法,会调用重写的<code>run()</code>方法。</p><p>3、如果<code>main</code>方法中,<code>start()</code>方法后面还有执行语句,并且<code>run()</code>方法中也有执行语句,<code>main</code>线程中会启动一个子线程<code>Thread-0</code>,主线程不会阻塞,主线程与子线程会交替执行。</p><p>注意:如果主线程执行完毕,但子线程未执行完,进程不会结束,所有线程执行完毕后,进程自动结束。</p><p>4、在主线程中为什么使用<code>start()</code>方法去调用<code>run()</code>方法,而不是直接调用<code>run()</code>方法,因为<code>run()</code>方法是一个普通方法,没有真正启动线程,如果调用<code>run()</code>方法,就会将<code>run()</code>方法执行完毕后,再执行<code>main</code>方法剩余语句,主线程就会阻塞。</p><p>所以上面程序都运算结果是:</p><pre class="brush:php;toolbar:false">主线程main 主线程i=1你好1Thread-0主线程i=2你好2Thread-0主线程i=3你好3Thread-0主线程i=4你好4Thread-0主线程i=5你好5Thread-0
public class Thread02 { public static void main(String[] args) { Dog dog = new Dog(); Thread thread = new Thread(dog); thread.start(); }}class Dog implements Runnable{ @Override public void run() { int count = 0; while (true) { System.out.println("小狗汪汪叫" + (++count) + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if (count == 10){ break; } } }}
1、因为Runnable
接口中没有start()
方法,所以需要代理
。
2、先在main方法中需要创建对象,然后创建一个Thread
对象,将之前创建的对象传入Thread
,借助Thread,调用start()
方法,创建线程。
3、建议使用Runnable
,因为实现Runnable接口更加适合多个线程共享一个资源的情况,避免了单继承的限制。
1、当线程执行完任务时会自动退出。
2、也可以使用变量控制run()
方法退出终止线程。
1、如果一个线程中的run()
方法内部是一个while(true){}
,即一个无限循环
。
2、我们可以在线程内部,创建一个boolean属性loop
,让loop = true,然后while(loop){}
。
3、再提供一个setLoop
한 프로세스에 여러 스레드가 있을 수 있습니다
. 예를 들어 Thunder는 파일을 다운로드하는 것과 같습니다. 프로세스이며 다운로드된 파일은 스레드와 동일합니다. 하나의 스레드만 실행하도록 허용
합니다. 5. 멀티스레딩
: 동시에여러 스레드를 실행할 수 있습니다
. 예를 들어 Thunder를 사용하면 동시에 여러 파일을 다운로드할 수 있습니다. 🎜🎜6. 🎜동시성🎜: 동시에 여러 작업이 교대로 수행
됩니다. 단일 코어 CPU로 달성되는 멀티태스킹은 동시성입니다. 🎜🎜7, 🎜Parallel🎜: 동시에 여러 작업이 동시에 수행
됩니다. 멀티 코어 CPU는 작업이 많을 때 동시성과 병렬성이 동시에 발생할 수 있습니다. 🎜🎜🎜2. 스레드의 기본 사용 🎜🎜스레드를 만드는 방법에는 두 가지가 있습니다. 🎜🎜1 Thread
클래스를 상속하고 run 메소드. 🎜🎜2. <code>Runnable
인터페이스를 구현하고 run
메서드를 재정의합니다. 🎜🎜참고: Thread
클래스는 Runnable
인터페이스를 구현합니다. 🎜🎜🎜(1) Thread 클래스를 상속하고 실행 메서드를 재정의합니다.🎜public class ThreadExit { public static void main(String[] args) throws InterruptedException { T t = new T(); t.start(); Thread.sleep(10000); t.setLoop(false); }}class T extends Thread{ private boolean loop = true; private int times = 0; @Override public void run() { while (loop){ System.out.println("hello" + (++times)); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } public void setLoop(boolean loop) { this.loop = loop; }}
Thread
클래스를 상속하고 run()을 다시 작성합니다. code> 메서드 다음에는 <code>main
메서드에서 객체를 생성하고 start()
메서드를 호출하여 스레드를 시작해야 합니다. 🎜🎜2. start()
메서드를 사용하면 재정의된 run()
메서드가 호출됩니다. 🎜🎜3. main
메서드의 경우 start()
메서드 뒤에 실행문이 있고, run() 메서드, 하위 스레드 <code>Thread-0
가 main
스레드에서 시작됩니다. 기본 스레드는 차단되지 않으며 기본 스레드와 하위 스레드는 차단되지 않습니다. 교대로 실행됩니다. 🎜🎜참고: 메인 스레드가 실행을 완료했지만 하위 스레드가 실행을 완료하지 않은 경우 모든 스레드가 실행을 완료한 후에도 프로세스가 자동으로 종료됩니다. 🎜🎜4. run()
를 직접 호출하는 대신 start()
메서드를 사용하여 메인 스레드에서 run()
메서드를 호출하는 이유 > 메소드? run()
메소드는 일반 메소드이고 실제로 스레드를 시작하지 않기 때문입니다. run()
메소드가 호출되면 run이 실행됩니다. ()
메소드가 실행된 후 main
메소드의 나머지 명령문이 실행되면 메인 스레드가 차단됩니다. 🎜🎜위 프로그램의 결과는 다음과 같습니다. 🎜public class ThreadMethod01 { public static void main(String[] args) throws InterruptedException { T t = new T(); t.setName("邱崇源"); t.setPriority(1); t.start(); for (int i = 0; i 🎜<a id="_Runnablerun_66">🎜(2) Runnable 인터페이스를 구현하고 실행 메서드를 다시 작성합니다🎜<pre class="brush:php;toolbar:false">public class ThreadMethod02 { public static void main(String[] args) throws InterruptedException { A a = new A(); a.start(); for (int i = 1; i 🎜1. 왜냐하면 실행 가능
start()
메서드이므로 에이전트
가 필요합니다. 🎜🎜2 먼저 기본 메소드에서 객체를 생성한 다음 Thread
객체를 생성하고, 이전에 생성된 객체 를 Thread
에 전달하고 Thread를 사용하여 를 호출합니다. start()
메소드를 사용하여 스레드를 생성합니다. 🎜🎜3. Runnable 인터페이스를 구현하는 것이 여러 스레드가 리소스를 공유하는 데 더 적합하고 단일 상속의 제한을 피하므로 Runnable
을 사용하는 것이 좋습니다. 🎜🎜🎜3. 스레드 종료 🎜🎜🎜(1) 기본 지침🎜🎜1. 스레드가 작업을 완료하면 자동으로 종료됩니다. 🎜🎜2. 변수를 사용하여 run()
메서드를 제어하여 종료된 스레드를 종료할 수도 있습니다. 🎜🎜🎜(2) 작업🎜🎜1. 스레드의 run()
메서드가 내부적으로 while(true){}
인 경우 >, 즉 무한 루프
입니다. 🎜🎜2. 스레드 내부에 부울 속성 루프
를 생성하고 loop = true로 설정한 다음 while(loop){}
로 설정합니다. 🎜🎜3. 다른 클래스에서 setLoop 메서드를 호출하고 부울 값을 변경하여 스레드 종료를 제어할 수 있도록 또 다른 setLoop
메서드를 제공합니다. 🎜🎜🎜🎜 (3) 코드 데모 🎜public class ThreadMethod03 { public static void main(String[] args) throws InterruptedException { MyDaemonThread myDaemonThread = new MyDaemonThread(); myDaemonThread.setDaemon(true); myDaemonThread.start(); for (int i = 1; i 🎜🎜🎜 4. 일반적인 스레드 방법 🎜🎜🎜🎜 (1) 첫 번째 그룹 🎜🎜1, 🎜setName🎜: 스레드 이름을 매개변수 이름과 동일하게 설정합니다. 🎜<p>2、<strong>getName</strong>:返回该线程名称。</p><p>3、<strong>start</strong>:使该线程开始执行,JAVA虚拟机底层调用该线程的start0方法。</p><p>4、<strong>run</strong>:调用线程对象的run方法。</p><p>5、<strong>setPriority</strong>:更改线程的优先级。</p><p>6、<strong>getPriority</strong>:获取线程的优先级。</p><p>7、<strong>sleep</strong>:在指定的毫秒数内,让当前正在执行的线程休眠。</p><p>8、<strong>interrupt</strong>:中断线程。</p><h4> <a id="_147"></a>注意事项:</h4><p>1、<code>start()</code>底层会创建新的线程,调用run(),<code>run()</code>就是一个简单的方法调用,<code>不会启动新线程</code>。</p><p>2、<code>中断线程一般用于中断正在休眠的线程</code>,并没有真正的结束线程,所以如果线程中每输出内容后,会调用<code>Thread.sleep()</code>进行休眠的话,我们可以调用<code>interrupt()</code>方法将其<code>提前唤醒</code>。</p><h4> <a id="_150"></a>代码演示:</h4><pre class="brush:php;toolbar:false">public class ThreadMethod01 { public static void main(String[] args) throws InterruptedException { T t = new T(); t.setName("邱崇源"); t.setPriority(1); t.start(); for (int i = 0; i <h4> <a id="_183"></a>(二)第二组</h4><p>1、<strong>yield</strong>:是一个<code>静态方法</code>,表示<code>线程的礼让</code>。让出<code>CPU</code>,让其他线程执行,但是<code>不一定成功</code>,因为这取决于CPU,如果CPU认为两个线程可以一起执行,则不进行礼让,所以<code>如果CPU的核数多,并且线程数少,礼让就会大概率失败</code>。</p><p>2、<strong>join</strong>:表示<code>线程的插队</code>,假如主线程与子线程正在交替运行,我们想<code>先让子线程执行</code>完毕,然后再让主线程执行,就可以使用线程插队,在主线程中,创建子线程对象,并调用<code>join</code>方法,可以实现线程插队,线程插队<code>一定会成功</code>,先<code>执行完插入线程任务后,再继续执行主线程</code>。</p><h4> <a id="_186"></a>代码演示:</h4><pre class="brush:php;toolbar:false">public class ThreadMethod02 { public static void main(String[] args) throws InterruptedException { A a = new A(); a.start(); for (int i = 1; i <h2> <a id="_219"></a>五、用户线程和守护线程</h2><p>1、<strong>用户线程</strong>:也叫<code>工作线程</code>,线程的任务执行完或通知方式结束。</p><p>2、<strong>守护线程</strong>:一般是<code>为工作线程服务</code>的,当<code>所有的用户线程结束</code>,<code>守护线程自动结束</code>。</p><h4> <a id="_222"></a>应用场景:</h4><p>如果有两个线程,主线程运行结束,但子线程是无限循环。我们想让主线程结束的同时,子线程也结束,就需要让子线程变成守护线程。</p><p>在主线程中,创建子线程对象,并调用<code>setDaemon(true)</code>,让子线程变成守护线程。</p><p>注意:一定要放在<code>start方法之前</code>。</p><h4> <a id="_226"></a>代码演示:</h4><pre class="brush:php;toolbar:false">public class ThreadMethod03 { public static void main(String[] args) throws InterruptedException { MyDaemonThread myDaemonThread = new MyDaemonThread(); myDaemonThread.setDaemon(true); myDaemonThread.start(); for (int i = 1; i <h2> <a id="_254"></a>六、线程的生命周期</h2><h4> <a id="1JDK__ThreadState__255"></a>1、JDK 中用 Thread.State 枚举表示了线程的几种状态</h4><p><img src="https://img.php.cn/upload/article/000/000/067/2235493b090cc60a6a3c1434c8852f59-0.png" alt="Java 지식 요약: 멀티스레딩 기초"></p><h4> <a id="2_257"></a>2、线程状态转换图</h4><p><img src="https://img.php.cn/upload/article/000/000/067/cfbba58b413c41b084c9e0cab6295dfe-1.png" alt="Java 지식 요약: 멀티스레딩 기초"></p><h2> <a id="_259"></a>七、线程的同步</h2><h4> <a id="1_260"></a>1、应用场景:</h4><p>假如有100张票,有三个线程同时进入该方法买票,票就有可能超卖。所以我们需要线程同步机制,保证数据在同一时刻,最多有一个线程访问。</p><p>可以采取同步方法,在方法中加入<code>synchronized</code>关键字。</p><p>也可以采用同步代码块,<code>synchronized(对象){}</code>。</p><p>注意:<code>synchronized是非公平锁</code>,如果这次第一个线程访问了数据,那么下一次第一个线程也有可能访问到数据。</p><p>如果同步方法是<code>非静态</code>的,那么锁可以是this,也可以是其他对象,但要求是同一个对象。</p><p>例:<code>synchronized(this)</code>。</p><p>如果同步方法是<code>静态</code>的,锁为当前类本身。</p><p>例:<code>synchronized(类名:class)</code>。</p><h4> <a id="2_270"></a>2、代码演示:</h4><pre class="brush:php;toolbar:false">public class SellTicket { public static void main(String[] args) { SellTicket02 sellTicket04 = new SellTicket02(); Thread thread1 = new Thread(sellTicket04); Thread thread2 = new Thread(sellTicket04); Thread thread3 = new Thread(sellTicket04); thread1.start(); thread2.start(); thread3.start(); }}class SellTicket02 implements Runnable { public static int ticket = 100; private boolean loop = true; public synchronized void sell() { if (ticket <h2> <a id="_309"></a>八、线程的死锁</h2><h4> <a id="1_310"></a>1、基本介绍</h4><p>多个线程都占用了对方的锁资源,但不肯相让,就导致了死锁,在编程中,一定要避免死锁的发生。</p><h4> <a id="2_312"></a>2、发生场景:</h4><p>例如:A和B的面前都各有两道门,A的第一道门是o1,第二道门是o2。B的第一道门是o2,第二道门是o1。他们的面前有两把锁,一个是o1锁,一个是o2锁,假如A抢到了o1锁,B抢到了o2锁,但是他们只可打开各自的第一道门,第二道门都没有打开,那么他们都无法释放自己的锁资源,又不可能相让,因此发生了死锁。</p><h4> <a id="3_314"></a>3、代码演示:</h4><pre class="brush:php;toolbar:false">public class DeadLock_ { public static void main(String[] args) { //模拟死锁现象 DeadLockDemo A = new DeadLockDemo(true); A.setName("A 线程"); DeadLockDemo B = new DeadLockDemo(false); B.setName("B 线程"); A.start(); B.start(); } }class DeadLockDemo extends Thread { static Object o1 = new Object();// 保证多线程,共享一个对象,这里使用 static static Object o2 = new Object(); boolean flag; public DeadLockDemo(boolean flag) {//构造器 this.flag = flag; } @Override public void run() { if (flag) { synchronized (o1) { System.out.println(Thread.currentThread().getName() + " 进入 1"); synchronized (o2) { System.out.println(Thread.currentThread().getName() + " 进入 2"); } } } else { synchronized (o2) { System.out.println(Thread.currentThread().getName() + " 进入 3"); synchronized (o1) { System.out.println(Thread.currentThread().getName() + " 进入 4"); } } } } }
当前线程的同步方法,同步代码块执行结束。
当前线程在同步代码块,同步方法中遇到break,return
。
当前线程在同步代码块,同步方法中出现了未处理的错误或异常
,导致异常结束。
当前线程在同步代码块,同步方法中执行的线程对象的wait方法
,当前线程暂停,并释放锁。
线程执行同步代码块和同步方法时,程序调用
Thread.sleep(),Thread.yield()
方法暂停当前线程的执行,不会释放锁。
线程执行同步代码块时,其他线程调用了该线程的suspend()
方法将该线程挂起,该线程不会释放锁。
推荐学习:《java视频教程》
위 내용은 Java 지식 요약: 멀티스레딩 기초의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!