Java中的多线程

进程是程序的一次执行过程,是系统运行程序的基本单位。而线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。

创建线程的方式

1.继承Thread类

定义一个继承自Thread的类,重写run()方法,创建这个类的实例然后调用start()方法启动新线程。

public class MyThread extends Thread {

    @Override
    public void run() {
        for (int i=1;i<=5;i++){
            System.out.println("MyThread的线程输出"+i);
        }
    }
}
public class Test1 {
    public static void main(String[] args) {
        Thread t= new MyThread();
        t.start();
        for (int i=1;i<=5;i++){
            System.out.println("主线程的输出"+i);
        }
    }
}

 2.定义Runnable接口

定义一个实现Runnable接口的类,重写run()方法,然后创建Thread实例时将其作为target传入,并调用start()。 

public class MyRunnble implements Runnable {
    @Override
    public void run() {
        for (int i=1;i<=5;i++){
            System.out.println("MyThread的线程输出"+i);
        }
    }
}
public class Test1 {
    public static void main(String[] args) {
        Runnable target= new MyRunnble();
        new Thread(target).start(); // new Thread(target)得到线程对象
        for (int i=1;i<=5;i++){
            System.out.println("主线程的输出"+i);
        }
    }
}

3.利用Callable接口,FutureTask类实现

此方法可返回线程执行结果

public class CallableAndFuturetask implements Callable<String>{
    private int n;
    public CallableAndFuturetask(int n){
        this.n =n;
    }

    @Override
    public String call() throws Exception{
        int sum = 0;
        for(int i =1;i<=n;i++){
            sum+=i;
        }
        return "线程求出的和是"+sum;
    }

}
public class Test1 {
    public static void main(String[] args) throws Exception {
        Callable<String> call = new CallableAndFuturetask(100);
        FutureTask<String> f1 = new FutureTask<>(call);
        new Thread(f1).start();

        String rs = f1.get();
        System.out.println(rs);
    }
}

Thread提供了很多与线程操作相关的方法 

public class MyThread extends Thread {

    @Override
    public void run() {
        Thread t = Thread.currentThread();
        for (int i=1;i<=5;i++){
            System.out.println(t.getName()+"输出"+i);
        }
    }
}

public class Test1 {
    public static void main(String[] args) {
        Thread t1 = new MyThread();
        t1.setName("1号线程");//为线程赋名字
        t1.start();
        System.out.println(t1.getName());

        Thread t2 = new MyThread();
        t2.setName("2号线程");//为线程赋名字
        t2.start();
        System.out.println(t2.getName()); //获得子线程的名字

        Thread m = Thread.currentThread();
        m.setName("最大的线程");//为线程赋名字
        System.out.println(m.getName()); //获得主线程的名字

        for (int i =1;i<=5;i++){
            System.out.println(m.getName()+"输出"+i);
        }
    }
}

如何保证线程安全

1.同步代码块:把访问资源的核心代码上锁,每次只允许一个线程加锁后进入,以保证此线程的安全;

synchronized (同步锁){

                访问共享资源的核心代码

}

实例方法使用this关键字进行加锁,静态方法使用类名.class作为锁对象

例如为银行取钱问题的核心代码加锁

package XianchengSaft;

public class Account {
    private String IdCard;
    private double balance;
    public  Account(){

    }
    public Account(String idCard, double balance) {
        IdCard = idCard;
        this.balance = balance;
    }

    public String getIdCard() {
        return IdCard;
    }

    public void setIdCard(String idCard) {
        IdCard = idCard;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
    public static void test(){
        synchronized (Account.class) {

        }
    }

    public void DrawMoney(double money){
        String name = Thread.currentThread().getName();
        synchronized (this) {
            if (this.balance>=money){
                System.out.println(name + "来取"+money+"成功");
                this.balance -= money;
                System.out.println(name + "取钱后剩余"+this.balance);
            }else{
                System.out.println(name + "来取钱,余额不足");
            }
        }
    }

    @Override
    public String toString() {
        return "Account{" +
                "IdCard='" + IdCard + '\'' +
                ", balance=" + balance +
                '}';
    }
}

2.同步方法:同步方法锁的范围更大,不利于程序的性能

修饰符 synchronized 返回值类型 方法名称(形参列表){

               操作共享资源的核心代码

}

package XianchengSaft;

public class Account {
    private String IdCard;
    private double balance;

    public Account() {

    }

    public Account(String idCard, double balance) {
        IdCard = idCard;
        this.balance = balance;
    }

    public String getIdCard() {
        return IdCard;
    }

    public void setIdCard(String idCard) {
        IdCard = idCard;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public static void test() {
        synchronized (Account.class) {

        }
    }

    public  synchronized void DrawMoney(double money) {
        String name = Thread.currentThread().getName();
        if (this.balance >= money) {
            System.out.println(name + "来取" + money + "成功");
            this.balance -= money;
            System.out.println(name + "取钱后剩余" + this.balance);
        } else {
            System.out.println(name + "来取钱,余额不足");
        }
    }

    @Override
    public String toString() {
        return "Account{" +
                "IdCard='" + IdCard + '\'' +
                ", balance=" + balance +
                '}';
    }
}

3.Lock锁 

package XianchengSaft;

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

public class Account {
    private String IdCard;
    private double balance;
    private final Lock lk =new ReentrantLock();

    public Account() {

    }

    public Account(String idCard, double balance) {
        IdCard = idCard;
        this.balance = balance;
    }

    public String getIdCard() {
        return IdCard;
    }

    public void setIdCard(String idCard) {
        IdCard = idCard;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public static void test() {
        synchronized (Account.class) {

        }
    }

    public  void DrawMoney(double money) {
        String name = Thread.currentThread().getName();
        try {
            lk.lock();
            if (this.balance >= money) {
                System.out.println(name + "来取" + money + "成功");
                this.balance -= money;
                System.out.println(name + "取钱后剩余" + this.balance);
            } else {
                System.out.println(name + "来取钱,余额不足");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lk.unlock();
        }
    }

    @Override
    public String toString() {
        return "Account{" +
                "IdCard='" + IdCard + '\'' +
                ", balance=" + balance +
                '}';
    }
}

synchronized 是什么?有什么用? 

synchronized是java中的关键字,可以保证多个线程访问资源的同步性。

synchronized修饰实例方法

synchronized void method() {
    //业务代码
}

 synchronized修饰静态方法

synchronized static void method() {
    //业务代码
}

synchronized修饰代码块

synchronized(this) {
    //业务代码
}

volatile关键字作用

  • 保证变量的可见性。如果被volatile关键字修饰的变量被一个线程修改的话,其他线程也能立马获取到变量修改后的值。
  • 禁止指令重新排序。指令排序就是编译器和处理器为了提高效率对程序优化的手段,可保证输出正确的结果,但不能保证操作顺序与代码顺序一致,因此会在多线程中出现问题,禁止了指令排序后可防止出现这一问题。

公平锁和非公平锁的区别

公平锁:锁被释放后,先申请的线程先得到锁。

非公平锁:锁被释放后,后申请的线程可能先得到锁,得到锁的机制是随机的或是按照优先级排列的。

### 回答1: Java 多线程可以通过创建 Thread 类的实例来实现。具体步骤如下: 1. 创建一个实现 Runnable 接口的类,该类实现 run() 方法。 ```java public class MyRunnable implements Runnable { public void run() { // 执行线程的操作 } } ``` 2. 创建一个 Thread 实例,并将实现了 Runnable 接口的类作为构造函数的参数。 ```java MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); ``` 3. 启动线程。 ```java thread.start(); ``` 此外,还可以通过继承 Thread 类来实现多线程。具体步骤如下: 1. 创建一个继承自 Thread 类的类,重写 run() 方法。 ```java public class MyThread extends Thread { public void run() { // 执行线程的操作 } } ``` 2. 创建 MyThread 的实例。 ```java MyThread myThread = new MyThread(); ``` 3. 启动线程。 ```java myThread.start(); ``` 在多线程的使用,需要注意线程安全的问题,比如共享变量的访问、同步操作等。可以使用 synchronized 关键字或者 Lock 接口来保证线程安全。 ### 回答2: 在Java多线程的使用是指程序同时运行多个线程,每个线程执行自己的任务。Java多线程的使用可以带来以下几点好处: 1. 提高程序的效率:多线程可以对多个任务进行并发处理,提高程序的运行效率。例如,可以将网络请求和UI界面分别放在两个不同的线程,这样即使网络请求比较耗时,UI界面也能进行响应,不会出现界面假死的情况。 2. 充分利用系统资源:多线程可以充分利用系统的处理器资源,提高系统的利用率。在多核处理器上运行多个线程,可以让每个核心都得到充分利用,提高系统的整体性能。 3. 实现异步编程:多线程可以实现异步编程,即一个线程执行后续操作,不需要等待另一个线程的完成。这样可以提高程序的响应速度。例如,可以使用多线程来进行文件下载,下载过程可以同时进行其他操作。 4. 处理复杂的并发情况:在一些需要处理多个并发操作的场景多线程可以提供更好的解决方案。例如,在并发访问共享资源的情况下,使用线程锁可以保证对共享资源的安全访问,避免数据冲突和一致性问题。 Java使用多线程可以通过创建Thread类的实例或者实现Runnable接口来实现。通过继承Thread类来创建线程,需要重写run方法,在run方法定义线程要执行的任务。通过实现Runnable接口来创建线程,需要实现run方法,并将实现了Runnable接口的对象作为参数传递给Thread类的构造方法。 总之,Java多线程的使用使得程序可以同时执行多个任务,提高了程序的效率和用户体验,并且能够处理复杂的并发情况。但需要注意多线程的安全性和线程之间的协作,避免出现数据冲突和一致性问题。 ### 回答3: Java多线程的使用是指在一个程序同时执行多个任务或者同时处理多个请求。多线程可以提高程序的并发性和响应性,可以将耗时的操作和任务分配给不同的线程来执行,从而提高程序的运行效率。 在Java多线程的使用主要依靠Thread类或者实现Runnable接口来创建线程。可以通过继承Thread类创建一个线程类,并重写run方法,在run方法定义需要执行的任务;也可以实现Runnable接口,创建一个Runnable对象,然后将该对象作为参数传递给Thread类的构造方法,创建一个线程对象。 使用多线程的好处是可以充分利用处理器的多核特性,同时进行多个任务,提高程序的运行效率。多线程还可以提高程序的响应性,当程序有耗时的操作时,可以将其放在一个独立的线程执行,防止主线程被阻塞,提高用户体验。 然而,多线程的使用也存在一些问题。首先是线程安全问题,多个线程同时访问共享资源可能导致数据不一致或者数据损坏。为解决这个问题,可以使用同步机制,如synchronized关键字或Lock接口,保证在同一时间只有一个线程能够访问共享资源。其次,多线程的创建和销毁会消耗系统资源,如果线程数量过多,可能会影响系统性能。因此,在使用多线程时应该合理控制线程的数量。另外,线程之间的协调和通信也是一个值得关注的问题,可以使用wait、notify、join等方法来实现线程间的协作。 总之,Java多线程的使用可以提高程序的并发性和响应性,但需要注意线程安全、资源消耗以及线程协调和通信等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个帅气的程序员ovo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值