java中实现多线程及同步方式

多线程实现方式

1)、实现Runnable接口,并实现run()方法

以下是主要步骤:

1、自定义类并实现Runnable接口,并实现run()方法。
2、创建Thread对象,用实现Runnable接口的对象作为参数实例化该Thread对象。
3、调用Thread的start()方法

class MyThread implements Runnale{
    public void run(){
        //线程执行代码块
    }

}

public class Test{
    public static void main(String []args){
        MyThread thread=new Thread();
        Thread t=new Thread(thread);
        t.start();

    }

}

2)、继承Thread类,重写run方法。

Thread本质上也是实现了Runnable接口的一个实例,它代表了一个线程实例,并且启动线程的唯一方法是通过Thread类的start方法。start方法是一个native(本地)
方法,他将启动一个新线程,并执行run方法(这是一个空方法);这种方式通过自定义类直接继承extends Thread,并重写run方法,就可以启动新线程并执行自己定义的run方法
需要注意的是:当start()方法调用之后并不会直接立即执行多线程代码,而是使得该线程变为可运行状态,什么时候运行多线程代码是由操作系统决定的

class MyThread extends Thread{
    public void run(){
    }
}

public class Test{
    public static void main(String [] args){
        MyThread thread=new Thread();
        thread.start();
    }
}

3)、实现Callable接口,重写call()方法

Callable随想实际上属于Executor框架中的功能类,Callable接口与Runnable接口类似,但是提供了比Runnable更强大的功能,主要表现如下:

  • Callable可以在任务结束后提供一个返回值,Runnable无法提供这个功能
  • Callable中的call方法可以抛出异常,而Runnable的run方法不能抛出异常
  • 运行Callable可以拿到一个future对象,future对象表示异步计算的结果,它提供了检查计算是否完成的方法。由于线程属于异步计算模型,所以无法从其他线程中得到方法的返回值,在这种情况下,就可以使用future来监视
    目标线程调用call方法的情况,当调用future的get方法以获取结果时,当前线程就会阻塞,直到call()方法结束后返回结果。
public class CallableAndFuture{
    public static class CallableTest implements Callable<String>{
        public String call() throws Exception {
            return "Hello world";
        }
    }

    public static void main(String []args){
        Executor threadpool=Executor.newSingleThreadExecutor();
        Future<String> future=thread.submit(new CallableTest());
        try{
            Sytem.out.println(future.get());//等待线程结束,并获取返回结果
            }catch(){

            }


    }

} 

线程提供同步机制

主要有三种实现同步机制的方式

1)synchronized 关键字

在java中,每一个对象都有一个对象锁与之相关联,该锁表明对象在任何时候只允许被一个线程所拥有,当一个线程调用对象的一段synchronized代码时,首先需要获得这个锁,然后去执行相应的代码,执行结束后,释放锁。
synchronized关键字主要有两种使用方式(synchronized方法和synchronied代码块),此关键字还可以运用于静态方法、类或某一个实例,但是对程序的效率影响很大。

  • synchronized方法:
public synchronized void mutiThreadAccess();

只要把多个线程访问的资源操作放到mutiThreadAccess方法中,就能够保证这个方法在同一刻只能被一个线程来访问,从而保证了多个线程访问的安全性。然而,当一个方法的方法体规模非常大的时候会影响程序执行效率。所以提供了synchronized代码块。

  • synchronized代码块

可以把任意的代码段申明为synchronized,也可以指定上锁的对象,有非常高的灵活性,

synchronized (syncObject){
    //访问同步代码
}

2)wait与notify

当使用synchronized来修饰某一个共享资源时候,如果线程A1在执行synchronized代码,另外一个线程A2也要同时执行同一对象的同一synchronized代码时,线程A2将要
等到线程A1执行完毕后才能执行。在这种情况下,可以使用wait方法和notify方法。

在synchronized代码执行期间,线程可以调用对象的wait方法,释放对象锁,进入等待状态,并且可以调用notify方法或notifyAll方法通知正在等待的其他线程,notify方法
仅唤醒一个线程(等待队列中的第一个线程),并允许它去获得锁,而notifyAll方法唤醒所有等待这个对象的线程,并允许他们去获得锁(并不是让所有唤醒的线程都获得锁,而是让他们去竞争);

3)Lock

jdk5 新增了Lock接口以及他的实现类ReentrantLock(重入锁),lock也可以用来实现多线程同步,具体而言,他提供了如下的一些方法来实现多线程的同步:

1)lock().以阻塞的方式来获取锁,也就是说,如果获取到了锁,则立即返回,如果其他线程持有锁,当前线程等待,直到获取锁后返回。
2)tryLock() 以非阻塞方式获取锁。只是尝试性的去获取锁,如果获取到锁,则立即返回true,获取不到则返回false,
3)tryLock(long timeout,TimeUnit unit) 如果获取了锁,立即返回true,否则,会等待参数给定时间单元,在等待的过程中,如果获取了锁,就返回true,如果等待时间超过,则返回false
4)lockInterruptibly().如果获取了锁,则立即返回,如果没有获取锁,则当前线程处于休眠状态,直到获得锁,或者当前线程被其他线程中断(会收到InterruptedException异常),他与lock方法最大的区别在于
:如果lock方法获取不到锁,则会一直处于阻塞状态,且会忽略interrupt方法。

final Lock lock=new ReentrantLock();
lock.lock();
Thread t1=new Thread(new Runnable(){
public void run{
try{
lock.lockInterruptibly();
//lock.lock();
}cathch(InterruptedException e){
System.out.println(“interrupted”);
}
}

});

t1.strart();
t1.interrupt();
Thread.sleep(1);

如果吧lock.lockInterruptibly()替换为lock.lock(),编译器将会提示lock.lock catch代码块无效,因为lock.lock()不会抛出异常,由此可见,lock方法会忽略interrupt()引发的异常。

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值