首页 > 编程语言 >Java多线程编程基础与高级特性

Java多线程编程基础与高级特性

时间:2024-10-08 20:23:09浏览次数:9  
标签:Java thread Thread 编程 start 线程 new 多线程 public

在现代软件开发中,多线程编程是一个重要的概念,它能够充分利用多核处理器的能力,提高程序的执行效率。Java 语言内置了对多线程的支持,使得开发者可以方便地创建和管理线程。

创建线程

1. 继承Thread类

这是最直接的方式,通过创建一个继承自Thread类的子类,并重写run()方法来定义线程的行为。之后,创建该子类的实例并调用start()方法来启动线程。

实现步骤:
1. 创建一个继承自Thread类的子类。
2. 重写run()方法,定义线程的执行逻辑。
3. 创建子类的实例。
4. 调用start()方法启动线程。

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程 " + Thread.currentThread().getName() + " 正在运行");
    }

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start(); // 启动线程
    }
}

2. 实现Runnable接口

这种方式更为推荐,因为它符合面向接口编程的原则,且不会受到单继承的限制。创建一个实现了 Runnable接口的类,实现run()方法。然后将Runnable实例传递给Thread类的构造器,最后调用Thread对象的start()方法来启动线程。

实现步骤:
1. 创建一个实现Runnable接口的类。
2. 实现run()方法,定义线程的执行逻辑。
3. 创建Runnable接口的实现类的实例。
4. 将Runnable实例传递给Thread类的构造器,创建Thread对象。
5. 调用Thread对象的start()方法启动线程。

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程 " + Thread.currentThread().getName() + " 通过 Runnable 运行");
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable(), "MyRunnableThread");
        thread.start(); // 启动线程
    }
}

3. 实现Callable接口

与Runnable接口类似,Callable接口也代表了一个任务,但它可以返回结果并且可以抛出异常。Callable接口中的call()方法返回一个结果值,并且可能抛出异常。通常,Callable任务的结果会被Future对象包装起来,通过ExecutorService执行Callable任务。

实现步骤:
1. 创建一个实现Callable接口的类。
2. 实现call()方法,定义线程的执行逻辑,并返回一个结果。
3. 创建Callable接口的实现类的实例。
4. 使用FutureTask包装Callable实例。
5. 将FutureTask实例传递给Thread类的构造器,创建Thread对象。
6. 调用Thread对象的start()方法启动线程。
7. 通过FutureTask的get()方法获取任务的执行结果。
 

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 100; i++) {
            sum += i;
        }
        return sum;
    }

    public static void main(String[] args) {
        MyCallable callable = new MyCallable();
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        Thread thread = new Thread(futureTask, "MyCallableThread");
        thread.start();

        try {
            Integer result = futureTask.get(); // 获取计算结果
            System.out.println("线程 " + Thread.currentThread().getName() + " 计算结果: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

线程的常用方法

1.start()
功能:启动线程,调用线程的run()方法。
示例:

     Thread thread = new Thread(() -> {
         System.out.println("线程运行中...");
     });
     thread.start();

2. run()
功能:线程的主体,包含线程要执行的代码。
示例:

  class MyThread extends Thread {
         @Override
         public void run() {
             System.out.println("线程 " + Thread.currentThread().getName() + " 正在运行");
         }
     }

3. join()
功能:等待当前线程终止。可以带一个超时参数,表示等待的时间(以毫秒为单位)。
示例:

 Thread thread1 = new Thread(() -> {
         try {
             Thread.sleep(1000);
             System.out.println("线程1运行完毕");
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     });

     Thread thread2 = new Thread(() -> {
         try {
             thread1.join(); // 等待 thread1 完成
             System.out.println("线程2运行完毕");
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     });

     thread1.start();
     thread2.start();

4. sleep(long millis)
功能:使当前正在执行的线程暂停指定的时间(以毫秒为单位),进入阻塞状态。
示例:

 Thread thread = new Thread(() -> {
         try {
             System.out.println("线程开始睡眠");
             Thread.sleep(2000); // 暂停2秒
             System.out.println("线程睡眠结束");
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     });
     thread.start();

5. yield()
功能:让出CPU,允许其他线程执行。不保证当前线程会立即停止执行。
示例:

 Thread thread = new Thread(() -> {
         for (int i = 0; i < 5; i++) {
             System.out.println("线程运行中...");
             if (i == 2) {
                 Thread.yield(); // 让出CPU
             }
         }
     });
     thread.start();

6. isAlive()
功能:判断线程是否还活着(即是否已经完成执行)。
示例:

 Thread thread = new Thread(() -> {
         try {
             Thread.sleep(2000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     });
     thread.start();

     while (thread.isAlive()) {
         System.out.println("线程还在运行...");
         try {
             Thread.sleep(500);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     }
     System.out.println("线程已结束");

7. interrupt()
功能:中断线程。如果线程处于阻塞状态(如sleep或wait),会抛出InterruptedException。
示例:

Thread thread = new Thread(() -> {
         try {
             System.out.println("线程开始睡眠");
             Thread.sleep(5000); // 暂停5秒
             System.out.println("线程睡眠结束");
         } catch (InterruptedException e) {
             System.out.println("线程被中断");
         }
     });
     thread.start();

     try {
         Thread.sleep(1000); // 主线程暂停1秒
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
     thread.interrupt(); // 中断线程

8. getName()和setName(String name)
功能:获取和设置线程的名称。
示例:

Thread thread = new Thread(() -> {
         System.out.println("线程名称: " + Thread.currentThread().getName());
     }, "MyThread");
     thread.start();

9. getId()
功能:获取线程的唯一标识符。
示例:

 Thread thread = new Thread(() -> {
         System.out.println("线程ID: " + Thread.currentThread().getId());
     });
     thread.start();

10. getPriority()和setPriority(int priority)
功能:获取和设置线程的优先级。优先级范围是1到10,默认值是5。
示例:

 Thread thread = new Thread(() -> {
          System.out.println("线程优先级: " + Thread.currentThread().getPriority());
      });
      thread.setPriority(Thread.MAX_PRIORITY); // 设置最高优先级
      thread.start();

11. isDaemon()和setDaemon(boolean on)
功能:获取和设置线程是否为守护线程。守护线程通常用于在后台执行一些服务,如垃圾回收。当所有非守护线程结束后,程序会自动退出。
示例:

 Thread thread = new Thread(() -> {
          while (true) {
              System.out.println("守护线程运行中...");
              try {
                  Thread.sleep(1000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
      });
      thread.setDaemon(true); // 设置为守护线程
      thread.start();

线程安全

在多线程环境中,多个线程可能会同时访问和修改共享资源,这可能导致数据不一致、死锁等问题。线程安全是指当多个线程访问某个类时,不管运行时环境如何调度这些线程,这个类的行为都能正确表现。确保线程安全的方法有很多,包括使用同步机制、不可变对象、原子类等。

线程安全的常见问题

数据竞争:多个线程同时读取和修改同一个变量,导致数据不一致。
死锁:两个或多个线程互相等待对方释放资源,导致所有线程都无法继续执行。
活锁:线程不断重复相同的操作,无法向前推进。
饥饿:某些线程因为长时间无法获得必要的资源而无法执行。

确保线程安全的方法

1. 同步机制

synchronized关键字
方法同步:在方法声明前加上synchronized关键字,确保同一时刻只有一个线程可以执行该方法。
代码块同步:在代码块前加上synchronized关键字,并指定一个对象作为锁,确保同一时刻只有一个线程可以执行该代码块。示例代码:

public class Counter {
    private int count = 0;

    // 方法同步
    public synchronized void increment() {
        count++;
    }

    // 代码块同步
    public void incrementWithBlock() {
        synchronized (this) {
            count++;
        }
    }

    public int getCount() {
        return count;
    }
}

public class Main {
    public static void main(String[] args) {
        Counter counter = new Counter();

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("最终计数: " + counter.getCount());
    }
}

ReentrantLock
提供了比synchronized更灵活的锁定操作,支持公平锁、非公平锁等。
需要手动获取和释放锁。示例代码:
 

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Counter {
    private int count = 0;
    private final Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public int getCount() {
        return count;
    }
}

public class Main {
    public static void main(String[] args) {
        Counter counter = new Counter();

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("最终计数: " + counter.getCount());
    }
}

2. 不可变对象

不可变对象一旦创建后,其状态就不能改变。
常见的不可变对象有String、Integer等。示例代码:

public final class ImmutableClass {
    private final int value;

    public ImmutableClass(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

public class Main {
    public static void main(String[] args) {
        ImmutableClass obj = new ImmutableClass(10);

        Thread t1 = new Thread(() -> {
            System.out.println("线程1读取值: " + obj.getValue());
        });

        Thread t2 = new Thread(() -> {
            System.out.println("线程2读取值: " + obj.getValue());
        });

        t1.start();
        t2.start();
    }
}

3. 原子类

java.util.concurrent.atomic包提供了一些原子操作类,如AtomicInteger、AtomicLong等。
这些类提供了原子性的操作,确保在多线程环境下不会出现数据竞争。示例代码:

import java.util.concurrent.atomic.AtomicInteger;

public class Counter {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }
}

public class Main {
    public static void main(String[] args) {
        Counter counter = new Counter();

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("最终计数: " + counter.getCount());
    }
}

标签:Java,thread,Thread,编程,start,线程,new,多线程,public
From: https://blog.csdn.net/b123321888/article/details/142767910

相关文章

  • 2024年Java最新面试题总结(五年经验)
    第一章、基础技术栈1.1)集合,string等基础问题1、arraylist,linkedlist的区别,为啥集合有的快有的慢①ArrayList它的底层是数组,有下标的概念,可以通过index下标直接定位元素,所以查询快;在增删时,会进行扩容判断和拷贝,所以增删慢。②LinkedList的底层是双向链表。每次查询都要循环......
  • springboot+vue【开题+程序+论文】基于javaweb的校友管理系统
    系统程序文件列表开题报告内容研究背景随着信息技术的迅猛发展和互联网的广泛普及,校友管理成为了各高校和校友会工作的重要组成部分。传统的校友管理方式,如纸质档案、电话沟通、邮件联络等,已难以满足当前高效、便捷、互动的管理需求。特别是在全球范围内,校友分布广泛,信息更......
  • 如何入门STM32单片机编程
    入门STM32单片机编程需要掌握以下内容:STM32的基本概念和特点:了解STM32系列单片机的特点、硬件结构、功能模块以及常用的开发工具和资源。KeilMDK开发环境的安装和使用:KeilMDK是一款非常常用的STM32开发工具,通过安装和配置KeilMDK,可以进行STM32的编译、下载和调试操作。......
  • java计算机毕业设计服装打版交易平台(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着电子商务的蓬勃发展和消费者个性化需求的日益增长,服装行业正经历着前所未有的变革。传统的服装设计与生产流程已难以满足市场对快速响应和定制化......
  • java计算机毕业设计宠物中心(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容宠物中心管理系统研究说明研究背景:随着社会经济的发展和人们生活水平的提高,宠物已经成为许多家庭的重要成员。宠物的健康、护理与福利问题日益受到人们的关......
  • java计算机毕业设计共享自习室管理系统(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在当今社会,随着教育资源的日益紧张和终身学习理念的深入人心,共享自习室作为一种新兴的学习空间形式,受到了越来越多学生的青睐。共享自习室不仅为学生......
  • java计算机毕业设计二手车交易网站(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着经济的持续发展和人民生活水平的不断提升,汽车已成为现代社会中不可或缺的交通工具。然而,随着新车市场的繁荣,二手车市场也逐渐崭露头角,成为消费者......
  • Java接口解读+场景分析
    文章目录1.接口快速入门2.接口基本介绍3.接口应用场景4.接口的使用细节5.接口VS继承6.接口的多态特性6.1多态的体现6.2多态的参数6.3多态数组6.4接口多态传递6.5接口继承的冲突1.接口快速入门我们的这个快速入门还是使用的这个日常生活里面的这个USB接口,我们下面的......
  • C#联合Visionpro编程学习记录,视觉中需要考虑旋转中心工况的计算方法探讨
    一、考虑旋转中心的工况解法,1,视觉中引导定位或者对位贴合时,机械手或者xyzr轴上手爪中心和末端轴中心不同轴时,就要考虑旋转中心问题;2,如果设备的CT要求没有很苛刻,可以采用2次拍照的方案解决,1次拍照后纠偏角度,然后在纠正角度后的位置2次拍照纠正x、y偏差; 看下图:第一次拍照得到红......
  • 每日学学Java开发规范,集合处理(附阿里巴巴Java开发手册(终极版))
    前言每次去不同的公司,码不同的代码,适应不同的规范,经常被老大教育规范问题,我都有点走火入魔的感觉,还是要去看看阿里巴巴Java开发规范,从中熟悉一下,纠正自己,码出高效,码出质量。想细看的可以去官网下载,或者下面自取阿里巴巴Java开发手册(终极版)五、集合处理【强制】关于ha......