ホームページ  >  記事  >  Java  >  Java スレッドの基本的な理解

Java スレッドの基本的な理解

零下一度
零下一度オリジナル
2017-07-18 17:54:201305ブラウズ

マルチスレッドを理解する前に、プロセスとスレッドを理解する必要があります:

プロセスとは、QQ、360 Butlerなど、コンピューター上の独立した各プログラムの実行アクティビティを指します

スレッドは、スレッド内の実行パスですプログラム内で複数のスレッドを同時に実行できる場合、このプログラムはマルチスレッドをサポートしていると言います。たとえば、Thunder ダウンロード ソフトウェアは複数のタスクを同時にダウンロードできます。

マルチスレッドとは何ですか?

マルチスレッドは、複数のタスクを同時に実行するものとして理解できます。通常、複数のスレッドを実行できるこの種のプログラムは、マルチスレッド プログラムと呼ばれます。 。

なぜマルチスレッドが必要なのでしょうか?

マルチタスクの同時作業方法として、マルチスレッドには次の特徴があります:

アプリケーションの応答を改善する

コンピューターの CPU 使用率を改善する

プログラム構造を改善する。長く複雑なプロセスを複数のスレッドに分割し、いくつかの独立または半独立した実行部分にすることができ、そのようなプログラムは理解しやすく、変更しやすくなります。

マルチスレッドプログラムを作成する方法と手順:

方法 1: Thread クラスを使用してスレッドを作成する

1) Thread クラスを継承するクラスを作成する

2) run メソッドをオーバーライドする//このメソッド そこに置かれたコンテンツが実行されるコンテンツです

3) 新しいこのカスタム Thread クラス

4) start メソッドを呼び出して、このスレッドを開始します (start メソッドには 2 つの機能があります。1 つはスレッドを開始すること、もう 1 つは run メソッドを呼び出すことです)

public class Test12 {public static void main(String[] args) {
        ThreadDemo t = new ThreadDemo();
        t.start();// 啓動ThreadDemo t2 = new ThreadDemo();
        t2.start();

        ThreadDemo t3 = new ThreadDemo();
        t3.start();for (int i = 0; i < 20; i++) {
            System.out
                    .println("线程" + Thread.currentThread().getName() + "正在运行");
        }
    }
}class ThreadDemo extends Thread {
    @Overridepublic void run() {for (int i = 0; i < 200; i++) {
            System.out
                    .println("线程" + Thread.currentThread().getName() + "正在运行");
            ;
        }
    }

}

重要なポイントの要約:

新しいスレッドでコードを実行するには、このコードをクラスの run 関数に配置する必要があります。 ran 関数が配置されている場所は、Thread クラス Class のサブクラスです

言い換えると、マルチスレッドを実装したい場合は、Threa クラスを継承するサブクラスを作成し、その run メソッドを書き直す必要があります

スレッドの場合、Thread サブクラス オブジェクトの run メソッドを呼び出しませんが、Thread サブクラス オブジェクトの start メソッド (Thread クラスから継承) を呼び出します。このメソッドは新しいスレッドを生成し、サブクラス オブジェクトの run メソッドを実行します。スレッドのコードセグメントは run メソッドに配置されているため、メソッドが実行された後、スレッドは終了します

public class Test {public static void main(String[] args) throws InterruptedException {
                    ThreadDemo t=new ThreadDemo();
                    t.start();                    while(true){
                        System.out.println("这是线程一输出的内容");
                        Thread.sleep(10);
                    }
                }
            }            
            class ThreadDemo extends Thread{public void run() {for (int i = 0; i < 50; i++) {
                        System.out.println("这是线程二输出的内容");
                    }
                }
            }

//例子,创建三个线程,和主线程同时运行public class Test2 {public static void main(String[] args) {
                MyThread t1=new MyThread();
                t1.start();
                
                MyThread t2=new MyThread();
                t2.start();
                
                MyThread t3=new MyThread();
                t3.start();                    for (int i = 0; i < 200; i++) {
                    System.out.println("主线程"+Thread.currentThread().getName()+"正在运行");
                }    
            }    
        }

方法二:使用Runable接口实现多线程

1)自定义一个类,implements Runnable接口

2)重写run方法

3)new出来这个自定的类//该类对象会作为Thread类构造函数的参数

4)new出Thread类

5)调用start方法

继承Thread类创建线程和实现Ruanble接口创建线程的区别

使用 Runable 接口创建多线程

1.适合多个相同的程序代码去处理同一资源的情况 把虚拟CPU (线程)同程序的代码 数据有效分离,较好的体现了面象对象

2.可以避免java单继承带来的局限 例如:当我们将已经继承了某类的一个类的子类放入多线程中,由于不能同时继承两个类,所以

什么情况下,不能采用继承Thread的方式,只好通过实现Ruanable?

1.当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runable接口类的实例

2.事实上,几乎所有的多线程都可以用Runnable接口方式

三、自定义线程

1) 线程的名字,一个运行中的线程总是有名字的,名字有两个来源,一个是虚拟机自己给的名字,

一个是你自己的定的名字。在没有指定线程名字的情况下,虚拟机总会为线程指定名字,并且主线程的名字总是mian,非主线程的名字不确定。

//Thread(String name) 可以在构造线程的时候,直接传入名字

//getName () 可以得到线程的名字

2) 获取当前线程的对象的方法是:Thread.currentThread();

3) 在上面的代码中,只能保证:每个线程都将启动,每个线程都将运行直到完成。一系列线程以某种顺序启动并不意味着将按该顺序执行。

对于任何一组启动的线程来说,调度程序不能保证其执行次序,持续时间也无法保证。

4) 当线程目标run()方法结束时该线程完成

5) 一旦线程启动,它就永远不能再重新启动。只有一个新的线程可以被启动,并且只能一次。一个可运行的线程或死线程可以被重新启动。

//t1.start(); 即这个操作只能一次,如果多次,将引发 java.lang.IllegalThreadStateException

class MyThread extends Thread{public void run() {for (int i = 0; i < 20000; i++) {
                    System.out.println("线程"+Thread.currentThread().getName()+"正在运行");
                }
            }
}

四、线程的状态

新建 (Born) : 新建的线程处于新建状态

就绪 (Ready) : 在创建线程后,start() 方法被调用它将处于就绪状态

运行 (Running) : 线程在开始执行时(run)进入运行状态

睡眠 (Sleeping) : 线程的执行可通过使用 sleep() 方法来暂时中止。在睡眠结束后,线程将进入就绪状态

等待 (Waiting) : 如果调用了 wait() 方法,线程将处于等待状态。用于在两个或多个线程并发运行时。

挂起 (Suspended) : 在临时停止或中断线程的执行时,线程就处于挂起状态。 //suspend() 已过时,有固定的死锁倾向

恢复 (Resume) : 在挂起的线程被恢复执行时,可以说它已被恢复。

阻塞 (Blocked) – 在线程等待一个事件时(例如输入/输出操作),就称其处于阻塞状态。

死亡 (Dead) – 在 run() 方法已完成执行或其 stop() 方法被调用之后,线程就处于死亡状态。 //stop 方法有两个重载,均已过时,有固定的不安全性

****

Java 中的线程优先级是在 Thread 类中定义的常量

NORM_PRIORITY : 值为 5

MAX_PRIORITY : 值为 10

MIN_PRIORITY : 值为 1

缺省优先级为 NORM_PRIORITY

****

有关优先级的方法有两个:

final void setPriority(int newp) : 修改线程的当前优先级

final int getPriority() : 返回线程的优先级

五、sleep 和 yield 的区别

1) sleep是Thread类的一个静态方法,该方法会让当前正在 执行的线程暂停执行,从而将执行机会让给其他线程执行。

sleep(long mills)参数指定当前线程暂停执行的时间,经过这段阻塞时间后,该线程会进入就绪状态,等候线程调度器的调度

sleep方法声明抛出了InterruptedException异常,所以调用sleep方法时要么在方法开始处抛出异常要么使用try{}..catch{}块进行捕获。

2) yield 方法只会给优先级相同或更高优先级的线程执行机会。yield不会将线程转入阻塞状态,只是强制当前线程进入就绪状态。

因此完全有可能某个线程调用yield方法暂停后,立即又获得处理器资源被执行。yield方法没有声明抛出任何异常。

// 通俗地说 yield()方法只是把线程的状态 由执行状态打回准备就绪状态

public void run() {for (int i = 0; i < 50; i++) {
        System.out.println(getName() + "--->" + i);if (i == 20) {
            Thread.yield();
            }
            }
            }public static void main(String[] args) {
                YieldThread t1 = new YieldThread("高级");
                t1.start();// 若当前线程优先级最高,那么即使调用了yield()方法,线程调度器又会将这个线程调度出来重新执行// t1.setPriority(Thread.MAX_PRIPORITY);YieldThread t2 = new YieldThread("低级");
                t2.start();
                t2.setPriority(Thread.MIN_PRIORITY);
                }

 六、线程同步 synchronized

原理讲解:任何对象都有一个标志位.是0或1 程序执行到这里.会检查这个对象的标志位,如果是1,那么向下执行,同时将标志信置为0

如果标志位为0,则线程发生阻塞.一直等到标志位为1 标志位又叫锁旗标

synchronized 又叫锁定了监视器 一个线程可以再进入线程锁定临视器.就象蓝球运动员再拿到球一样。

class SaleThread2  implements Runnable{//static int ticket=1000;private int ticket;public SaleThread2(int ticket){this.ticket=ticket;
            }
            
            String lockStr="";//Object obj=new Object();public void run() {while(true){synchronized (lockStr) {  //锁 ,锁旗标if(ticket>0){try{
                                    Thread.sleep(10);    
                            }catch(Exception ex){
                                ex.printStackTrace();
                            }
                            
                            System.out.println("线程"+Thread.currentThread().getName() +"正在卖第"+ticket--+"张票");
                        }else{break;
                        }
                    }
                }    
            }
        }

 

以上がJava スレッドの基本的な理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。