Java教程

java--线程与多线程(Callable与Runnable,synchronized)

本文主要是介绍java--线程与多线程(Callable与Runnable,synchronized),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

  • 一、创建线程的方式
    • 1.继承Thread类与线程的常用方法
    • 2.实现Runnable接口
    • 3.实现Callable接口
  • 二、解决线程安全问题
    • 1.同步代码块
    • 2.同步方法
    • 3.与synchronized 相关的三个方法
    • 4.Lock锁方式(JDK5)
    • (附)死锁示例

一、创建线程的方式

1.继承Thread类与线程的常用方法

  • 功能类继承Thread
  • 实例化功能类对象
  • 功能类对象.start()
package thread;

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        TestThread1 thread1 = new TestThread1();
        // 9.设置优先级
        thread1.setPriority(Thread.MAX_PRIORITY);

        // 8.开启线程
        thread1.start();
        for (int i = 1; i <= 100; i++) {
            if (i % 2 ==0 ){
                // 1.Thread.currentThread(),获取当前线程 .getName()获取名字
                System.out.println(Thread.currentThread().getName()+"--"+i);
            }
            if (i == 49){
                // 2.join(),thread1先执行到结束
                thread1.join();
            }
            if (i == 80){
                // 3.stop(),强制结束线程,不推荐使用
                Thread.currentThread().stop();
            }
            // 4.isAlive()判断是否存活
            System.out.println(thread1.isAlive());
        }
    }
}
class TestThread1 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 ==0 ){
                // 5.setName()设置线程名称
                Thread.currentThread().setName(this.getClass().getName());
                System.out.println(Thread.currentThread().getName()+"--"+i);
            }
            if (i % 20 == 0){
                // 6.释放当前线程的CPU执行权,等价this.yield;或Thread.currentThread().yield();
                yield();//
            }
            if (i % 30 == 0){
                try {
                    // 7.当前线程阻塞1秒,等价this.sleep或Thread.currentThread().sleep
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

2.实现Runnable接口

  • 功能类实现Runnable接口,并重写run方法
  • 功能类对象作为Thread构造器的参数创建Thread对象
  • Thread对象.start()
package thread;

public class RunnableTest {
    public static void main(String[] args) {
        TestThread tt = new TestThread();
        Thread thread = new Thread(tt);
        Thread thread1 = new Thread(tt);
        Thread thread2 = new Thread(tt);
        thread.start();
        thread1.start();
        thread2.start();
    }
}
class TestThread implements Runnable{
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            if (i % 2 ==0 ){
                System.out.println(Thread.currentThread().getName()+"--"+i);
            }
        }
    }
}

3.实现Callable接口

package thread.ticket;

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

public class Window implements Callable<Integer> {
    private int ticketCount = 100;
    @Override
    public Integer call() {
        while (ticketCount > 0) {
            synchronized (this) {
                int i = 101 - ticketCount;
                System.out.println(Thread.currentThread().getName() + "出售第" + i + "张票");
                ticketCount -= 1;
            }
        }
        return ticketCount;
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Window window = new Window(); // 创建实现Callable接口的类的对象
        FutureTask futureTask = new FutureTask(window); // 上面的对象作为参数创建FutureTask的对象
        FutureTask futureTask1 = new FutureTask(window); // 上面的对象作为参数创建FutureTask的对象
        FutureTask futureTask2 = new FutureTask(window); // 上面的对象作为参数创建FutureTask的对象
        Thread thread = new Thread(futureTask);// FutureTask实现了Runnable,以此作为参数创建线程
        Thread thread1 = new Thread(futureTask);// FutureTask实现了Runnable,以此作为参数创建线程
        Thread thread2 = new Thread(futureTask);// FutureTask实现了Runnable,以此作为参数创建线程
        thread1.setName("aaaa");
        thread.setName("bbbb");
        thread2.setName("cccc");
        thread.start();
        thread1.start();
        thread2.start();
        Object o = futureTask.get(); // Window类的call方法返回值
        System.out.println(o);
    }
}

二、解决线程安全问题

1.同步代码块

package thread.ticket;

public class Window implements Runnable{
    public int ticketCount = 100;
    @Override
    public void run() {
        // synchronized (同步监视器){ 需要被同步的代码; }
        synchronized (this){
            while (ticketCount>0){
                int i = 101 - ticketCount;
                System.out.println(Thread.currentThread().getName()+"出售第"+i+"张票");
                ticketCount -= 1;
            }
        }
    }

    public static void main(String[] args) {
        Window w1 = new Window();
        Thread thread = new Thread(w1);
        Thread thread1 = new Thread(w1);
        Thread thread2 = new Thread(w1);

        thread1.start();
        thread.start();
        thread2.start();
    }
}

2.同步方法

package thread.ticket;


public class Window implements Runnable{
    public int ticketCount = 100;
    @Override
    public void run() {
        sale();
    }
    // 返回值类型前加synchronized关键字
    public synchronized void sale(){
        while (ticketCount>0){
            int i = 101 - ticketCount;
            System.out.println(Thread.currentThread().getName()+"出售第"+i+"张票");
            ticketCount -= 1;
        }
    }
    public static void main(String[] args) {
        Window w1 = new Window();
        Thread thread = new Thread(w1);
        Thread thread1 = new Thread(w1);
        Thread thread2 = new Thread(w1);

        thread1.start();
        thread.start();
        thread2.start();
    }
}

3.与synchronized 相关的三个方法

package thread.ticket;

import java.util.concurrent.locks.ReentrantLock;

public class Window implements Runnable{
    private int ticketCount = 100;
    @Override
    public void run() {
        while (ticketCount > 0) {
            synchronized (this) {
                // notify(); // 唤醒一个其他的线程(按优先级)
                // 唤醒所有wait中的线程
                notifyAll();
                int i = 101 - ticketCount;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "出售第" + i + "张票");
                ticketCount -= 1;
                try {
                    wait(); // 将本线程阻塞,释放同步监视器
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) {
        Window window = new Window();
        // 使用同一个对象创建多个线程
        Thread thread1 = new Thread(window);
        Thread thread2 = new Thread(window);
        Thread thread3 = new Thread(window);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

4.Lock锁方式(JDK5)

package thread.ticket;

import java.util.concurrent.locks.ReentrantLock;

public class Window implements Runnable{
    private int ticketCount = 100;
    private ReentrantLock lock = new ReentrantLock(); // 参数默认为false,true时采用先进先出公平方式
    @Override
    public void run() {
        lock.lock(); // 在需要同步的代码前加锁
        try {
            while (ticketCount>0){
                int i = 101 - ticketCount;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"出售第"+i+"张票");
                ticketCount -= 1;
            }
        } finally {
            lock.unlock(); // 必须解锁
        }
    }
    public static void main(String[] args) {
        Window window = new Window();
        // 使用同一个对象创建多个线程
        Thread thread1 = new Thread(window);
        Thread thread2 = new Thread(window);
        Thread thread3 = new Thread(window);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

(附)死锁示例

package thread.ticket;
public class Window implements Runnable{
    public static void main(String[] args) {
        StringBuffer aa = new StringBuffer("aa");
        StringBuffer bb = new StringBuffer("bb");

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (aa) {
                    aa.append("cc");
                    bb.append("dd");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (bb) {
                        aa.append("11");
                        bb.append("22");
                        System.out.println(aa);
                        System.out.println(bb);
                    }
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (bb){
                    aa.append("11");
                    bb.append("22");
                    synchronized (aa){
                        aa.append("cc");
                        bb.append("dd");
                        System.out.println(aa);
                        System.out.println(bb);
                    }
                }
            }

        }).start();

    }
}
这篇关于java--线程与多线程(Callable与Runnable,synchronized)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!