多线程

java多线程

继承Thread:

/*
    线程的实现:继承Thread 重写run 方法,start 启动线程
 */
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i=0;i<5;i++){
            System.out.println(MyThread.this.toString()+":"+i);
        }
    }

    @Test
    public void test(){
        Thread thread = new MyThread();
        thread.start();
    }
}

执行结果:

Thread[Thread-1,5,main]:0
Thread[Thread-1,5,main]:1
Thread[Thread-1,5,main]:2
Thread[Thread-1,5,main]:3
Thread[Thread-1,5,main]:4

实现Runnable接口:

/*
    多线程的实现:通过实现Runnable接口 覆写 run 方法,再用Thread 启动
 */
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i=0;i<5;i++){
            System.out.println(MyRunnable.this.toString()+":"+i);
        }
    }

    @Test
    public void test(){
        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

执行结果:

Base.thread.com.MyRunnable@1ff4714f:0
Base.thread.com.MyRunnable@1ff4714f:1
Base.thread.com.MyRunnable@1ff4714f:2
Base.thread.com.MyRunnable@1ff4714f:3
Base.thread.com.MyRunnable@1ff4714f:4

实现Callable接口:

/*
    虽然 Runnable 可以避免单继承的局限性,但是该接口不能返回操作结果。
    故从 jdkl.5 开始 有了Callable 接口。
    但是必须要用Thread类来启动线程,而Thread类里没有定义任何构造方法可以直接接受Callable接口对象实例,
    故,从jdk1.5 开始,提供了一个FutureTask<V> 的类
 */
public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        for (int i=0;i<5;i++){
            System.out.println(MyCallable.this.toString()+":"+i);
        }
        return "success";
    }

    @Test
    public void  test() throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<String>(new MyCallable());
        Thread thread = new Thread(futureTask);
        thread.start();
        String result = futureTask.get();
        System.out.println(result);
    }
}

执行结果:

Base.thread.com.MyCallable@6f961649:0
Base.thread.com.MyCallable@6f961649:1
Base.thread.com.MyCallable@6f961649:2
Base.thread.com.MyCallable@6f961649:3
Base.thread.com.MyCallable@6f961649:4
success

多线程常用的操作方法

线程的命名与取得

方法类型描述
public Thread(Runnable tatget, String name)构造实例化线程对象,接收Runnable接口子类对象,同时设置线程名称
public final void setName(String name)普通设置线程名字
public final String getName()普通取得线程名字

线程的休眠

Thread.sleep(millis); //毫秒

线程优先级

线程优先级操作:

方法或常量类型描述
public static final int MAX_PRIORITY常量最高优先级,value = 10
public final static int NORM_PRIORITY常量中等优先级,value = 5
public final static int MIN_PRIORITY常量最低优先级,value = 1
public final void setPriority(int newPriority)普通设置线程优先级
public final int getPriority()普通取得线程优先级

线程的同步与死锁

同步问题的引出

卖票 :

public class TicketRunnable implements Runnable {
    private int ticket = 5;
    @Override
    public void run() {
        for (int i = 0;i<20;i++){
            if (ticket >0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "卖票,ticket =" + this.ticket--);
            }
        }
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Runnable ticketThread = new TicketRunnable();
        new Thread(ticketThread,"票贩子A").start();
        new Thread(ticketThread,"票贩子B").start();
        new Thread(ticketThread,"票贩子C").start();
        new Thread(ticketThread,"票贩子D").start();
    }
}

执行结果:

票贩子D卖票,ticket =5
票贩子A卖票,ticket =3
票贩子B卖票,ticket =4
票贩子C卖票,ticket =5
票贩子D卖票,ticket =2
票贩子B卖票,ticket =1
票贩子C卖票,ticket =2
票贩子A卖票,ticket =0

注意每次执行结果均可能不同,但是会出现同一张票卖了多次的,甚至出现 ticket 为负数的情况

这就是同步问题.解决方案:

  • 同步代码块:利用synchronized 包装代码块,但是需要指定同步对象,一般设置为this
  • 同步方法:利用synchronize定义方法

同步代码块:

public void run() {
    for (int i = 0;i<20;i++){
        synchronized (this){
            if (ticket >0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "卖票,ticket =" + this.ticket--);
            }
        }

    }
}

同步方法:

public void run() {
    for (int i = 0;i<20;i++){
       sale();

    }
}

private synchronized void sale() {
    if (ticket >0){
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "卖票,ticket =" + this.ticket--);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值