Java 多线程

多线程是指在一个程序中同时执行多个线程,每个线程都是独立的执行流。Java是一种支持多线程编程的编程语言,它提供了一些内置的类和方法,用于创建和管理多线程应用程序。以下是在Java中使用多线程的一般步骤:

线程创建及启动

1、通过扩展Thread类创建线程 我们可以通过扩展Thread类,并覆盖Thread类中的run ( )方法来创建一个线程。其中,run( )方法中的代码就是让线程完成的工作。

2、通过实现Runnable接口创建线程 除了通过扩展Thread类来创建线程外,也可以通过实现Runnable接口来创建一个线程。该接口只有一个run()方法需要实现。一个类实现Runnable接口后,如果要创建一个线程,需要先创建该类的一个实例,然后将该实例作为参数传递给Thread类的一个构造方法来创建一个Thread类实例。

Tread:

// 定义一个继承Thread类的自定义线程类
class MyThread extends Thread {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getId() + " Value " + i);
        }
    }
}

public class ExampleThread {
    public static void main(String args[]) {
        // 创建两个线程实例
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();

        // 启动线程
        thread1.start();
        thread2.start();
    }
}

Runnable接口:

要先创建一个带有 runnable接口的类,再创建Tread类。

// 定义一个实现Runnable接口的自定义线程类
class MyRunnable implements Runnable {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getId() + " Value " + i);
        }
    }
}

public class ExampleThread {
    public static void main(String args[]) {
        // 创建一个Runnable实例
        MyRunnable myRunnable = new MyRunnable();

        // 创建两个线程,分别传入Runnable实例
        Thread thread1 = new Thread(myRunnable);
        Thread thread2 = new Thread(myRunnable);

        // 启动线程
        thread1.start();
        thread2.start();
    }
}

线程状态及转化

新建状态(New Thread)

当使用New关键字新创建一个线程时,这时线程处于新建状态(New Thread)。处于新建状态的线程并没有真正执行程序代码,它只是一个空的线程对象,系统甚至没有分配资源给它。分配线程所需的资源是start()方法要完成的工作。

可运行状态(Runnable)

一旦一个线程调用了start()方法,线程就进入可运行状态(Runnable)。处于可运行状态的线程未必真的在运行,这时系统已经为该线程分配了它所需要的资源,至于何时运行,要取决于操作系统何时为该线程分配时间,因为只有操作系统才有权决定CPU的时间分配。当线程被分配到时间开始执行时,这个线程进入运行中状态。

阻塞状态(Blocked)

阻塞状态也可以称作不可运行状态,即由于某种原因使线程不能执行的一种状态。这时即便是CPU正处在空闲状态,也无法执行该线程。导致一个线程进入阻塞状态可能有如下几个原因: 线程调用了sleep()方法; I/O流中发生了线程阻塞; 线程调用了wait()方法; 线程调用了suspend()方法(已过时); 线程要锁住一个对象,但该对象已被另一个线程锁住。

死亡状态(Dead)

线程进入死亡状态一般有两种原因: 线程执行完,自然死亡。 异常终止run()方法(如调用stop()方法,stop()方法已过时)。

线程同步与互斥

 为了保证程序运行的正确性,那些需要被多个线程共享的数据需要被加以限制,即一次只允许一个线程来使用它。我们把这种一次只允许一个线程使用的资源称为“临界资源”,访问这种临界资源的代码称为“临界区”。 Java中采用对象锁的机制来处理临界区的互斥问题。Java引入了synchronized关键字,可以用来修饰实例方法,一旦一个方法被该关键字修饰,这个方法被称为“同步方法”。每个对象具有一把锁,我们将其称为“对象锁”。

 线程同步

多个相互合作的线程彼此间需要交换数据,则必须保证各线程运行步调一致,如一个线程在没有得到与其合作的线程发来的信息之前,处于等待状态,一直到信息到来时才被唤醒继续执行。如果相互合作的程序配合得不好,程序运行结果将会产生问题。

线程同步例子:

public class QueueOld {
    protected Object[] data;
    protected int writeIndex;
    protected int readIndex;
    protected int count;

    public QueueOld(int size) {
        data = new Object[size];
    }

    public synchronized void write(Object value) {
        data[writeIndex++] = value;
        System.out.println("写入数据: " + value);
        writeIndex %= data.length;
        count += 1;
    }

    public synchronized void read() {
        Object value = data[readIndex++];
        System.out.println("读取数据: " + value);
        readIndex %= data.length;
        count -= 1;
    }

    public static void main(String[] args) {
        QueueOld q = new QueueOld(5);
        new Writer(q);
        new Reader(q);
    }
}

class Writer implements Runnable {
    QueueOld queue;

    Writer(QueueOld target) {
        queue = target;
        new Thread(this).start();
    }

    public void run() {
        int i = 0;
        while (i < 100) {
            queue.write(new Integer(i));
            i++;
        }
    }
}

class Reader implements Runnable {
    QueueOld queue;

    Reader(QueueOld source) {
        queue = source;
        new Thread(this).start();
    }

    public void run() {
        int i = 0;
        while (i < 100) {
            queue.read();
            i++;
        }
    }
}

在进行多线程编程时,有可能由于处理不当而出现“死锁”现象。如果几个线程相互等待而都无法被唤醒正常执行,而每个线程又不会放弃自己占有的资源,这就导致了“死锁”。Java并不能避免死锁,因此,必须由程序员在编程时自己避免出现死锁问题。

你可能感兴趣的:(java,开发语言)