マルチスレッド技術の概要
処理する
メモリ内で実行されているアプリケーションを指し、各プロセスには独立したメモリスペースがあります
糸
はプロセス内の実行パスであり、メモリスペースを共有し、スレッドを自由に切り替えることができ、同時実行します。プロセスには少なくとも1つのスレッドがあります。
スレッドは実際にはプロセスに基づいてさらに分割されます。プロセスが開始された後、内部のいくつかの実行パスをいくつかのスレッドに分割できます
記事のディレクトリ
スレッドスケジューリング
タイムシェアリングスケジューリング
すべてのスレッドが順番にCPUを使用する権利を使用し、各スレッドがCPUを占有する時間を均等に分散します。
プリエンプティブスケジューリング
CPUを使用するために、優先度の高いスレッドを優先します。スレッドの優先度が同じである場合、1つがランダムに選択されます(スレッドのランダム性)。Javaは
プリエンプティブスケジューリング。
CPUはプリエンプティブスケジューリングモードを使用して、複数のスレッドを高速で切り替えます。CPUの新しいコアでは、一度に実行できるスレッドは1つだけであり、複数のスレッド間のCPUの切り替え速度は、私たちが思っているよりも速く、同時に実行されているように見えます。実際、マルチスレッドプログラムはプログラムの実行速度を向上させることはできませんが、プログラムの実行効率を向上させ、CPU使用率を高めることができます。
同期および非同期
同期:キューに入れられた実行、非効率的ですが安全です。
非同期:同期実行、高効率ですが安全でないデータ。
並列および並行性
同時実行性:同じ期間に発生する2つ以上のイベントを指します。
パラレル:二つ以上のイベントがで発生し、同じ時間(同時に)。
マルチスレッドテクノロジーを有効にする
1.スレッドを継承します
public class MyThread extends Thread{
/**
*run方法就是线程要执行的任务方法
*/
@Override
public void run(){
//这里的代码 就是一条新的执行路径.
//这个执行路径的方式,不是调用run方法,而是通过Thread对象的start()来启动任务。
for(int i=0;i<10;i++){
System.out.println("锄禾日当午"+i);
}
}
}
public static void main(String[] args){
MyThread m = new MyThread();
m.start();
for(int i=0;i<10;i++){
System.out.println("汗滴禾下土"+i);
}
}
各スレッドには独自のスタックスペースがあり、ヒープメモリを共有します
2.Runnableを実装する
Runnableの実装には、スレッドの継承に比べて次の利点があります。
- タスクを作成してからスレッドをスレッドに割り当てることで実現されるマルチスレッドは、複数のスレッドが同じタスクを同時に実行する状況に適しています。
- 単一継承の制限を回避できます。
- タスクはスレッド自体から分離されているため、プログラムの堅牢性が向上します。
- 後で学習するスレッドプールテクノロジは、実行可能タイプのタスクを受け入れますが、スレッドタイプのスレッドは受け入れません。
public class MyRunnable implements Runnable{
@Override
public void run(){
//线程的任务
for(int i=0;i<10;i++){
System.out.println("锄禾日当午"+i);
}
}
}
public static void main(String[] args){
//实现Runnable
//1. 创建一个任务对象
MyRunnable r = new MyRunnable();
//2. 创建一个线程,并为其分配一个任务
Thread t = new Thread(r);
//3. 执行这个线程
t.start();
for(int i=0;i<10;i++){
System.out.println("锄禾日当午"+i);
}
}
3.リターンワーススレッドで呼び出し可能
実行可能与呼び出し可能
接口定义
//Callable接口
publicinterfaceCallable<V> {
Vcall()throwsException;
}
//Runnable接口
public interface Runnable {
publicabstractvoidrun();
}
RunnableはCallableと同じです
1.都是接口
2.都可以编写多线程程序
3.都采用Thread.start()启动线程
RunnableはCallableとは異なります
1.Runnable没有返回值;Callable可以返回执行结果
2.Callable接口的call()允许抛出异常;Runnable的run()不能抛出
Callableは戻り値を取得します
Callalble接口支持返回执行结果,需要调用FutureTask.get()得到,
此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞。
スレッド名を設定して取得する
public static void main(String[] args){
//如何获取线程的名称
System.out.println(Thread.currentThread().getName());
newThread(new MyRunnable(),"锄禾日当午").start();
}
static class MyRunnable implements Runnable{
@Override
public void run(){
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args){
//如何获取线程的名称
System.out.println(Thread.currentThread().getName());
newThread(new MyRunnable(),"").start();
newThread(new MyRunnable(),"").start();
newThread(new MyRunnable(),"").start();
}
static class MyRunnable implements Runnable{
@Override
public void run(){
System.out.println(Thread.currentThread().getName());
}
}
スレッドスリープ
public static void main(String[] args){
//线程的休眠 sleep
for(int i=0;i<10;i++){
System.out.println(i);
Thread.sleep(1000);//休息一秒钟,指定时间休眠
}
}
糸の詰まり
耗时操作
スレッドの中断
public static void main(String[] args){
//线程中断
//一个线程是一个独立的执行路径,他是否应该结束,应该由自身决定
//早期提供stop 过时,会直接插死
}
package thread;
public class Demo5 {
public static void main(String[] args) {
//线程中断
//y一个线程是一个独立的执行路径,它是否结束应该由其自身决定
Thread t1 = new Thread(new MyRunnable());
t1.start();
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//给线程t1添加中断标记
t1.interrupt();
}
static class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//e.printStackTrace();
System.out.println("发现了中断标记,线程自杀");
return;
}
}
}
}
}
デーモンスレッド
package thread;
public class Demo6 {
public static void main(String[] args) {
//线程分为守护线程和用户线程
//用户线程:当一个进程不包含任何的存活的用户线程时,进行结束
//守护线程:守护用户线程的,当最后一个用户线程结束时,所有守护线程自动死亡。
Thread t1 = new Thread(new MyRunnable());
//设置守护线程
t1.setDaemon(true);
t1.start();
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}