java 多线程 独立处理_JAVA多线程下高并发的处理经验

线程的几种实现:1、继承Thread类,重写该类的run方法class MyThread extendsThread {private int i = 0;

@Overridepublic voidrun() {for (i = 0; i < 100; i++) {

System.out.println(Thread.currentThread().getName()+ " " +i);

}

}

}public classThreadTest {public static voidmain(String[] args) {

Thread myThread1= new MyThread(); //创建一个新的线程 myThread1 此线程进入新建状态

myThread1 .start(); //调用start()方法使得线程进入可执行状态

}

}2、实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象class MyRunnable implementsRunnable {private int i = 0;

@Overridepublic voidrun() {for (i = 0; i < 100; i++) {

System.out.println(Thread.currentThread().getName()+ " " +i);

}

}

}public classThreadTest {public static voidmain(String[] args) {

Runnable myRunnable= new MyRunnable(); //创建一个Runnable实现类的对象

Thread thread1= new Thread(myRunnable); //将myRunnable作为Thread target创建新的线程

thread1.start();//调用start()方法使得线程进入就绪状态

}

}

}3、使用Callable和Future接口创建线程。具体是创建Callable接口的实现类,并实现clall()方法。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程public classThreadTest {public static voidmain(String[] args) {

Callable myCallable = new MyCallable(); //创建MyCallable对象

FutureTask ft = new FutureTask(myCallable); //使用FutureTask来包装MyCallable对象

for (int i = 0; i < 100; i++) {

System.out.println(Thread.currentThread().getName()+ " " +i);if (i == 30) {

Thread thread= new Thread(ft); //FutureTask对象作为Thread对象的target创建新的线程

thread.start(); //线程进入到就绪状态

}

}

System.out.println("主线程for循环执行完毕..");try{int sum = ft.get(); //取得新创建的新线程中的call()方法返回的结果

System.out.println("sum = " +sum);

}catch(InterruptedException e) {

e.printStackTrace();

}catch(ExecutionException e) {

e.printStackTrace();

}

}

}class MyCallable implements Callable{private int i = 0;//与run()方法不同的是,call()方法具有返回值

@OverridepublicInteger call() {int sum = 0;for (; i < 100; i++) {

System.out.println(Thread.currentThread().getName()+ " " +i);

sum+=i;

}returnsum;

}

}

继承Thread和实现Runnable接口实现多线程的区别:

继承Thread类、实现Runnable接口,在程序开发中只要是多线程,肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下优势:

​1、可以避免由于Java的单继承特性而带来的局限;

​2、增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;

​3、适合多个相同程序代码的线程区处理同一资源的情况。

线程的优先级别:

java线程可以通过setPriority()方法对其设定一个优先级别,高优先级别的线程比低优先级别的线程有更高的几率得到先执行,优先级可以用0到10的整数表示,0为最低优先级别、10为最高优先级别。当线程调度器决定那个线程需要调度时,会根据这个优先级进行调度选择;1)Thread类有三个优先级静态常量:MAX_PRIORITY为10,为线程最高优先级;MIN_PRIORITY取值为1,为线程最低优先级;NORM_PRIORITY取值为5,为线程中间位置的优先级。默认情况下,线程的优先级为NORM_PRIORITY。2)一般来说优先级别高的线程先获取cpu资源先运行,但特殊情况下由于现在的计算器都是多核多线程的配置,有可能优先级低的线程先执行,具体的执行还是看JVM调度来决定。

几种线程同步的方法:1、使用synchronized获取对象互斥锁:这种方式是最常用也比较安全的一种方式,采用synchronized修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁。每个对象都有一个monitor(锁标记),当线程拥有这个锁标记时才能访问这个资源,没有锁标记便进入锁池。任何一个对象系统都会为其创建一个互斥锁,这个锁是为了分配给线程的,防止打断原子操作。每个对象的锁只能分配给一个线程,因此叫做互斥锁。我们在使用同步的时候进来爸锁的粒度控制的精细一点,有时候没必要锁整个方法,只需要锁一个代码块即可达到我们的业务需求,这样避免其他线程阻塞时间过长造成性能上的影响。packageper.thread;importjava.io.IOException;public classTest {private int i = 0;private Object object = newObject();public static void main(String[] args) throwsIOException {

Test test= newTest();

Test.MyThread thread1= test.newMyThread();

Test.MyThread thread2= test.newMyThread();

thread1.start();

thread2.start();

}class MyThread extendsThread{

@Overridepublic voidrun() {synchronized(object) {

i++;

System.out.println("i:"+i);try{

System.out.println("线程"+Thread.currentThread().getName()+"进入睡眠状态");

Thread.currentThread().sleep(10000);

}catch(InterruptedException e) {//TODO: handle exception

}

System.out.println("线程"+Thread.currentThread().getName()+"睡眠结束");

i++;

System.out.println("i:"+i);

}

}

}

}2、使用特殊域变量volatile实现线程同步:volatile修饰的变量是一种稍弱的同步机制,因为每个线程中的成员变量都会对这个对象的一个私有拷贝,每个线程获取的数据都是从私有拷贝内存中获取,而volatile修饰之后代表这个变量只能从共享内存中获取,禁止私有拷贝。在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比synchronized关键字更轻量级的同步机制。从内存的可见性上来看,写入volatile变量相当于退出同步代码块,而读取volatile变量相当于进入同步代码块。但代码中过度依赖于volatile变量来控制同步状态,往往比使用锁更加不安全,使用同步机制会更安全一些。当且仅当满足以下所有条件时,才应该使用volatile变量: 1、对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。 2、该变量没有包含在具有其他变量的不变式中。classBank {//需要同步的变量加上volatile

private volatile int account = 100;public intgetAccount() {returnaccount;

}//这里不再需要synchronized

public void save(intmoney) {

account+=money;

}

}3、使用重入锁Lock实现线程同步: 在jdk1.5以后java.util.concurrent.locks包下提供了这一种方式来实现同步访问。因为synchronized同步之后会存在一个阻塞的过程,如果这个阻塞的时间过久,严重影响我们代码的质量以及带来系统性能上的问题。因为我们需要一种机制,让等待的线程到达一定时间之后能够响应中断,这就是Lock的作用。另外lock还可以知道线程有没有成功获取到对象锁,synchronized无法做到。Lock比synchronized提供更多的功能。但要注意的是:1)Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问;2)Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。packagecom.dylan.thread.ch2.c04.task;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;/*** This class simulates a print queue

**/

public classPrintQueue {/*** 创建一个ReentrantLock实例*/

private final Lock queueLock=newReentrantLock();/*** Method that prints a document

*@paramdocument document to print*/

public voidprintJob(Object document){//获得锁

queueLock.lock();try{

Long duration=(long)(Math.random()*10000);

System.out.printf("%s: PrintQueue: Printing a Job during %d seconds\n",Thread.currentThread().getName(),(duration/1000));

Thread.sleep(duration);

}catch(InterruptedException e) {

e.printStackTrace();

}finally{//释放锁

queueLock.unlock();

}

}

}

注:关于Lock对象和synchronized关键字的选择:

a.最好两个都不用,使用一种java.util.concurrent包提供的机制,能够帮助用户处理所有与锁相关的代码。

b.如果synchronized关键字能满足用户的需求,就用synchronized,因为它能简化代码

c.如果需要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁4、使用ThreadLocal管理变量:如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响;ThreadLocal 类的常用方法:

ThreadLocal() : 创建一个线程本地变量

get() : 返回此线程局部变量的当前线程副本中的值

initialValue() : 返回此线程局部变量的当前线程的"初始值"set(T value) : 将此线程局部变量的当前线程副本中的值设置为valuepublic classBank{//使用ThreadLocal类管理共享变量account

private static ThreadLocal account = new ThreadLocal(){

@OverrideprotectedInteger initialValue(){return 100;

}

};public void save(intmoney){

account.set(account.get()+money);

}public intgetAccount(){returnaccount.get();

}

}5、使用阻塞队列实现线程同步:自从Java 1.5之后,在java.util.concurrent包下提供了若干个阻塞队列,或Redis消息队列等来实现同步等等。。。

java多线程并发的业务场景:在互联网的大环境下很多场景都对并发要求越来越高,像天猫双十一秒杀、春运火车票抢票、微信抢红包、以及一些业务对某种资源的请求数量的控制、以及一些业务需要整个系统的输入输出顺序一致性等问题,这些都需要考虑到并发导致的数据安全性问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值