プロセス:スレッドはプロセスから切り離せません。プロセスとは何かについてお話ししましょう。(エクスプローラーを開くと、現在実行中のプロセスが表示されます)。
スレッド:これは、プロセスおよび実行パス内の単一の順次制御フローです。
シングルスレッド:プロセスに実行パスが1つしかない場合、そのプロセスはシングルスレッドプログラムになります。
マルチスレッド:プロセスに複数の実行パスがある場合、そのプロセスはマルチスレッドプログラムになります。
マルチスレッドを実装する
方式一:继承Thread类
1.定义一个类MyThread 继承Thread类
2.在MyThread类中重写Run()方法
3.创建对象
4.启动线程 用Start方法
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println(i);
}
}
}
public class MyThreadDemo {
public static void main(String[] args) {
MyThread m1=new MyThread();
MyThread m2=new MyThread();
m1.start();
m2.start();
}
}
方法2:实现Runnable接口
定义一个MyRunnable类,实现Runnable接口
在MyRunnable类中重写run方法
创建MyRunnable类的对象
创建Thread类对象,将MyRunnable对象作为构造方法的参数
启动线程
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
public class MyRunnableDemo {
public static void main(String[] args) {
MyRunnable my=new MyRunnable();
Thread t1=new Thread(my);
Thread t2=new Thread(my);
t1.start();
t2.start();
}
}
質問:なぜrun()メソッドを書き直すのですか?
runメソッドは、スレッドによって実行されるコードをカプセル化するために使用されます。
run()メソッドとstart()メソッドの違いは何ですか?
run():スレッドによって実行されるコードをカプセル化して直接呼び出します。これは、通常のメソッドの呼び出しと同等です。
start():スレッドを開始すると、このスレッドのrun()メソッドがJVMによって呼び出されます。
スレッド名を設定して取得する
public static void main(String[] args) {
MyThread m1=new MyThread();
m1.setName("王");
String name = m1.getName();
System.out.println(name);
}
スレッドスケジューリング
Javaはプリエンプティブスケジューリングを使用します。優先度の高いスレッドは最初にCPUを使用します。同じ優先順位で、1つがランダムに選択されます。優先度の高いスレッドは、CPUタイムスライスが少し多くなります。
MyThread m1 = new MyThread();
MyThread m2 = new MyThread();
MyThread m3 = new MyThread();
//获取线程的优先级,优先级默认是5,最高是10,最小是1.
// System.out.println(m1.getPriority());//5
// System.out.println(m2.getPriority());//5
// System.out.println(m3.getPriority());//5
//更改线程的优先级
m1.setPriority(1);
m2.setPriority(10);
m3.setPriority(1);
スレッド制御
//Thread.sleep(); 使当前正在执行的线程停留,指定的秒数,然后继续执行。
//vodi join();等待这个线程死亡。
//下面例子,m1,结束后,m2,m3才运行。
MyThread m1 = new MyThread();
MyThread m2 = new MyThread();
MyThread m3 = new MyThread();
m1.setName("王");
m2.setName("李");
m3.setName("孙");
m1.start();
try {
m1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
m2.start();
m3.start();
//void setDaemon(boolean on) 将此线程标记为守护线程,运行的线程都是守护线程时,java虚拟机将退出。
//例子:当主线程刘备结束后,关羽和张飞也退出线程。
MyThread m1 = new MyThread();
MyThread m2 = new MyThread();
m1.setName("关羽");
m2.setName("张飞");
Thread.currentThread().setName("刘备");
m1.setDaemon(true);
m2.setDaemon(true);
m1.start();
m2.start();
for (int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
スレッドのライフサイクル
スレッドの同期
ケース:チケット購入システム、3つのウィンドウが同時にチケットを購入し、複数のスレッドを使用します。
public class SellTicket implements Runnable{
private int tickets=100;
@Override
public void run() {
while(true){
if (tickets>0){
try{
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}
}
public class SellTickerDmo {
public static void main(String[] args) {
SellTicket st=new SellTicket();
Thread t1=new Thread(st,"窗体1");
Thread t2=new Thread(st,"窗体2");
Thread t3=new Thread(st,"窗体3");
t1.start();
t2.start();
t3.start();
}
}
上記の書き込みは問題を引き起こします、それはチケットであり、何度も販売されています。必要なのは、共有データを操作する複数のステートメントをロックすることです。つまり、それらをロックすると、一度に1つだけがそれらにアクセスできます。
問題を解決するための同期コードブロック方式:
public class SellTicket implements Runnable{
private int tickets=1000;
private Object obj=new Object();
@Override
public void run() {
while(true){
//加锁
synchronized (obj){
if (tickets>0){
try{
Thread.sleep(10);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}
}
}
同期の問題を解決するためのロック:
Lockはインターフェースであり、直接インスタンス化して使用することはできません。その実装クラスReentrantLockを使用できます。
主な方法は、ロックを取得してロックをキャストすることです。
public class SellTicket implements Runnable{
private int tickets=1000;
private Lock lock =new ReentrantLock();
@Override
public void run() {
while(true){
try{
lock.lock();
if (tickets>0){
try{
Thread.sleep(10);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"zhang票");
tickets--;
}
}finally {
lock.unlock();
}
}
}
}
スレッドセーフクラス:
同期を実行してスレッドの安全性を確保する必要がある場合は、次のクラスを使用できます。それらの基礎となるメソッドはすべて、synchronizedでロックされてい ます。
StringBuffer sbf=new StringBuffer();
//下面这两个是线程安全的集合,但是我们一般不会去用。用下面的方法转!
Vector ve=new Vector();
Hashtable ht=new Hashtable();
//下面方法可以把集合转成 线程安全的。
List<String> list = Collections.synchronizedList(new ArrayList<String>());