Java基础:多线程

本文介绍了Java多线程的基础知识,包括线程的功能、创建方式、状态转换和线程同步。通过实例展示了如何创建线程,如继承Thread或实现Runnable接口,并解释了线程的不同状态,如就绪、运行、阻塞和等待。还提到了线程同步的重要性,以及相关的关键方法如synchronized、wait、notify等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、操作系统能同时运行多个应用程序,每个应用程序就是一个进程
   一个进程可以同时运行多个线程,每个线程负责处理一个任务

2、线程的功能:一个应用程序可以同时去完成多个功能

3、应用程序启动后,会自动创建一个主线程(Android中叫UI线程),其他的线程都称之子线程

4、线程创建线程:
A、创建一个类继承自Thread或者实现Runnable接口,他们都需要重写run()方法,该方法是线程的主体,功能代码必须放在run()方法

B、调用Thread的start()方法启动线程,该方法会自动调用run()方法,run()方法中的代码执行结束后,线程会自动销毁

C、线程对象不能重复启动,比较下面的写法

    Thread t = new Thread();
     t.start();
     t.start();
     上面写法错误,因为线程完成后会销毁,所以不能重复调用start()
     ----------------
     线程启动之前一定要先创建
     new Thread().start();
     new Thread().start();

5、创建线程的方法
A、继承Thread类,该方法用得比较少

public class MyThread extends Thread{
    public void run(){
        Thread.sleep(1000);//休眠
    }
}

MyThread t = new MyThread();
t.start();

B、实现Runnable接口,99%的时候都用此方法   

     public class MyThread implements Runnable{
          public void run(){
               Thread.sleep(1000);
          }
     }
     Thread t = new Thread(new MyThread());
     t.start();

案例1:在应用程序中,两个任务同时运行,一个是显示时钟,另一个显示偶数。

public class EvenTask implements Runnable{
     @Override
     public void run() {
          for(int i = 0; i < 100; i ++){
               if(i % 2 == 0){
                    System.out.println(i);
               }
               try {
                    Thread.sleep(10);
               } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               }
          }
     }
}

public class TimeTask implements Runnable{
     private Date now = new Date();

     @Override
     public void run() {
          while(true){
               //打印现在的时间
               System.out.println(now.toLocaleString());
               //更新时间
               now.setTime(System.currentTimeMillis());
              
               //输入一次时间后线程休眠1秒钟
               try {
                    Thread.sleep(1000);
               } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               }
          }
     }
}

public class Client {
     public static void main(String[] args) {
          Thread time = new Thread(new TimeTask());
          time.start();
         
          Thread even = new Thread(new EvenTask());
          even.start();
         
         
          /*new Thread(new Runnable() {
               @Override
               public void run() {
                   
               }
          }).start();*/
     }
}

案例2: 利用多线程求解某范围素数,每个线程负责1000范围:线程1找1-1000;线程2找1001-2000;线程3找2001-3000。编程程序将每个线程找到的素数及时打印。

/**
* 判断素数
* @author Administrator
*
*/
public class Prime {
     /**
     * 判断n是否为素数,如果是,返回true,否则返回false
     * @param n
     * @return
     */
     public static boolean isPrime(int n){
          for(int i = 2; i < n; i ++){
               if(n % i == 0){
                    return false;
               }
          }
          return true;
     }
}

public class Thread1 implements Runnable{
     @Override
     public void run() {
          for(int i = 1; i <= 1000; i ++){
               if(Prime.isPrime(i)){
                    System.out.println(i);
               }
              
               try {
                    Thread.sleep(10);
               } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               }
          }
     }

}

public class Thread2 implements Runnable{
     @Override
     public void run() {
          for(int i = 1001; i <= 2000; i ++){
               if(Prime.isPrime(i)){
                    System.out.println(i);
               }
              
               try {
                    Thread.sleep(10);
               } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               }
          }
     }
}

public class Thread3 implements Runnable{
     @Override
     public void run() {
          for(int i = 2001; i <= 3000; i ++){
               if(Prime.isPrime(i)){
                    System.out.println(i);
               }
              
               try {
                    Thread.sleep(10);
               } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               }
          }
     }
}

public class Test {
     public static void main(String[] args) {
          Thread t1 = new Thread(new Thread1());
          Thread t2 = new Thread(new Thread2());
          Thread t3 = new Thread(new Thread3());
         
          try {
               t1.start();
               //t1.join();
               t2.start();
               //t2.join();
               t3.start();
          } catch (InterruptedException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
          }
     }
}     

6、线程的状态及转换
A、线程对象创建后,线程处于就绪状态
B、调用start()方法后,线程处于可运行状态,不一定立即运行,因为此时CPU正在处理其他的任务
C、CPU处理处于可运行状态的线程,线程马上会调用run()方法并处于运行状态
D、线程在运行过程中,如果调用了sleep()或join()方法,线程会处于阻塞状态(阻塞状态是指线程还在内存中,但不会执行任务)
E、线程在运行过程中,调用了yield()方法,该线程会主动出让CPU,此时,线程会处理可运行状态
F、线程在运行过程中,如果调用了wait()方法,则线程会处理等待状态,必须要通过notify()或notifyAll()才能唤醒线程

7、Thread中的方法
start():启动线程
run():线程主体,完成任务
sleep():休眠
join():让线程处于阻塞状态,CPU处理完前面的线程后再处理后面的线程
yield():主动让出CPU的控制权
wait():线程处于等待状态,此时,线程成了植物人
notify()、notifyAll():专门用于唤醒处于等待状态的线程

8、线程状态转换关系


9、线程同步用于保证一个共享资源在同一时刻只能有一个线程访问,如果其他线程也要访问,就必须等待。

10、线程同步时,使用不同的方法需要明白的共享资源
A、同步方法
synchronized public void method(){}
共享对象是this
即:同步方法定义在哪个类中,该类的对象就是共享对象

class A{
     synchronized public void method(){

     }
}
A a = new A(); -> 此时,对象a就是共享对象

案例:

/**
* 共享资源
*
* @author Administrator
*
*/
public class ShareResource {
     private int n;

     public synchronized void addSelf() {
          for (int i = 0; i < 10; i++) {
               System.out.println(Thread.currentThread().getName() + ":" + n++);

               try {
                    Thread.sleep(100);
               } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               }
          }
     }
}

线程1:
public class Task1 implements Runnable {
     private ShareResource sr;

     public Task1(ShareResource sr) {
          super();
          this.sr = sr;
     }

     @Override
     public void run() {
          sr.addSelf();//同步方法
     }
}

线程2:
public class Task2 implements Runnable {
     private ShareResource sr;

     public Task2(ShareResource sr) {
          super();
          this.sr = sr;
     }

     @Override
     public void run() {
          sr.addSelf();
     }
}

测试:
public class Test {
     public static void main(String[] args) {
          ShareResource sr = new ShareResource();
          new Thread(new Task1(sr)).start();
          new Thread(new Task2(sr)).start();
     }
}

B、同步块
synchronized(object){}
共享对象是object
同步块通常定义在线程中

案例:

共享资源:
public class ShareResource2 {
     private int n;

     public void addSelf() {
          for (int i = 0; i < 10; i++) {
               System.out.println(Thread.currentThread().getName() + ":" + n++);

               try {
                    Thread.sleep(100);
               } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               }
          }
     }
}

线程1:
public class Task3 implements Runnable {
     private ShareResource2 sr;//共享对象

     public Task3(ShareResource2 sr) {
          super();
          this.sr = sr;
     }

     @Override
     public void run() {
          synchronized(sr){
               sr.addSelf();//同步方法
          }
     }
}

线程2:
public class Task4 implements Runnable {
     private ShareResource2 sr;

     public Task4(ShareResource2 sr) {
          super();
          this.sr = sr;
     }

     @Override
     public void run() {
          synchronized(sr){
               sr.addSelf();//同步方法
          }
     }
}

测试:
public class Test2 {
     public static void main(String[] args) {
          ShareResource2 sr = new ShareResource2();
          new Thread(new Task3(sr)).start();
          new Thread(new Task4(sr)).start();
     }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值