java 线程

java线程方法 以及 作用简单介绍。

sleep:

使线程 等待设定时间,不会释放持有锁

join:

当前线程.join方法会阻断下一个线程,在该线程运行完毕以前。该线程运行完毕以后才能运行下一个线程。
参数join():1.myThread.join(millis); 设置等待时间 如果过了时间就回执行下面的线程
2.myThread.join(millis, nanos);比上面多了一个纳秒时间单位

setDeamon :

参数为boolean如果参数为true那么该线程设置为后台线程,反之不是后台线程,设置当前线程为守护线程,一般守护线程的优先级比较低。
线程分为:1.守护线程 2.用户线程。守护线程是为用户线程提供服务的,Java的垃圾回收机制就有这方面机制。
用户线程和守护线程区别在与:虚拟机,当所有用户线程全部结束后,虚拟机退出,守护线程也就退出结束了。
网上解释: 虚拟机的退出,所有的用户线程退出了 虚拟机也就退出了,守护线程也就结束了(不管守护线程有没有运行)
Daemon 要在thread.start()前执行。
Daemon 中生产的线程都是Daemon类型的
Daemon是永远不会访问固态资源的,如文件,数据库,因为他有可能在任何时候甚至一个操作都会中断。

myThread.setPriority(newPriority) :

设置优先级 Java线程中有默认的有限常量MIN_PRIORITY=1;NORM_PRIORITY=5;MAX_PRIORITY=10;

myThread.interrupt():

中断线程,并不会马上执行线程中断, Thread.interrupt()方法不会中断一个正在运行的线程。它的作用是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。interrupt方法并不是强制终止线程,它只能设置线程的interrupted状态,
而在线程中一般使用一下方式:while (!Thread.currentThread().isInterrupted() && more work to do)而被block的线程(sleep() or join())在被调用interrupt时会产生InterruptException,此时是否终止线程由本线程自己决定

wait()

释放该线程的监控器 (释放锁) 导致当前线程等待另一个线程调用java.lang.Object.notify()方法或java.lang.Object.notifyAll()方法的对象。换句话说,该方法的行为与执行调用wait(0)完全一样。
当前线程必须拥有该对象的监视器。线程释放该监视器的所有权,并等待另一个线程通知等待该对象的监视器的线程通过对notify方法或notifyAll方法的调用来唤醒。线程然后等待,直到它能够重新获得监视器的所有权并恢复执行。
正如在一个参数版本中,中断和假的wakeups是可能的,并且这个方法应该总是在一个循环中使用

notify 和 notifyAll:

这又是一个刁钻的问题,因为多线程可以等待单监控锁,Java API 的设计人员提供了一些方法当等待条件改变的时候通知它们,但是这些方法没有完全实现。notify()方法不能唤醒某个具体的线程,所以只有一个线程在等待的时候它才有用武之地。而notifyAll()唤醒所有线程并允许他们争夺锁确保了至少有一个线程能继续运行。

官方文档:notify:

唤醒一个在这个对象监视器上等待的线程。如果有任何线程在等待这个对象,则选择其中一个线程被唤醒。选择是任意的,并在实现的自由裁量权下发生。线程通过调用一个等待方法在对象的监视器上等待。
在当前线程放弃对该对象的锁定之前,唤醒的线程将无法继续前进。唤醒的线程将以通常的方式与可能正在积极竞争的其他线程进行竞争;例如,被唤醒的线程在成为锁定该对象的下一个线程时没有可靠的特权或劣势。
该方法只能由一个线程调用,该线程是该对象监视器的所有者。线程以以下三种方式之一成为对象监视器的所有者:
通过执行该对象的同步实例方法。
通过执行与对象同步的同步语句的主体。
对于类的对象,通过执行该类的同步静态方法。

不同点1. notfiy 一次只有一个线程可以拥有一个对象的监视器。
不同点2. notfiy是针对当前的一个线程,唤醒一个在这个对象监视器上等待的线程。notfiyall 唤醒在这个对象监视器上等待的所有线程

yidle:

停止当前线程 与wait()不同。
Yield方法可以暂停当前正在执行的线程对象,让其它有相同优先级的线程执行。它是一个静态方法而且只保证当前线程放弃CPU占用而不能保证使其它线程一定能占用CPU,执行yield()的线程有可能在进入到暂停状态后马上又被执行。

myThread.checkAccess(); // 确定当前运行的线程是否有修改此线程的权限。
myThread.isAlive(); //线程是否活着,返回结果是Boolean
myThread.setUncaughtExceptionHandler(null);
myThread.yield(); //屈服
myThread.holdsLock(obj);//持有锁 参数 obj 用于测试锁定所有权的对象。返回 如果当前线程持有指定对象上的监视器锁,则为true。
myThread.getAllStackTraces()//得到全部的线程 堆栈行踪轨迹 这个一般使用在线程池
myThread.getStackTrace();//得到这个线程 堆栈行踪轨迹
myThread.enumerate(tarray);枚举
myThread.dumpStack()//一般是调试时使用的
myThread.activeCount();//返回当前线程及其子线程中活动线程的总数,
myThread.currentThread();//currentThread 现在的线程 当前的线程

常见问题
如何在Java中实现线程?

在语言层面有两种方式。java.lang.Thread 类的实例就是一个线程但是它需要调用java.lang.Runnable接口来执行,由于线程类本身就是调用的Runnable接口所以你可以继承java.lang.Thread 类或者直接调用Runnable接口来重写run()方法实现线程。

Thread 类中的start() 和 run() 方法有什么区别?

这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。

ava中Runnable和Callable有什么不同?

Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5增加的。它们的主要区别是Callable的 call() 方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象。

Java多线程中调用wait() 和 sleep()方法有什么不同?

Java程序中wait 和 sleep都会造成某种形式的暂停,它们可以满足不同的需要。wait()方法用于线程间通信,如果等待条件为真且其它线程被唤醒时它会释放锁,而sleep()方法仅仅释放CPU资源或者让当前线程停止执行一段时间,但不会释放锁。

Java中的fork join框架是什么?

fork join框架是JDK7中出现的一款高效的工具,Java开发人员可以通过它充分利用现代服务器上的多处理器。它是专门为了那些可以递归划分成许多子模块设计的,目的是将所有可用的处理能力用来提升程序的性能。fork join框架一个巨大的优势是它使用了工作窃取算法,可以完成更多任务的工作线程可以从其它线程中窃取任务来执行。

写出3条你遵循的多线程最佳实践
写并发代码来提升性能的时候也会遵循某些最佳实践。以下三条最佳实践我觉得大多数Java程序员都应该遵循:

  1. 给你的线程起个有意义的名字。 这样可以方便找bug或追踪。OrderProcessor, QuoteProcessor or TradeProcessor 这种名字比 Thread-1. Thread-2 and Thread-3 好多了,给线程起一个和它要完成的任务相关的名字,所有的主要框架甚至JDK都遵循这个最佳实践。
  2. 避免锁定和缩小同步的范围,锁花费的代价高昂且上下文切换更耗费时间空间,试试最低限度的使用同步和锁,缩小临界区。因此相对于同步方法我更喜欢同步块,它给我拥有对锁的绝对控制权。
  3. 多用同步类少用wait 和 notify , 首先,CountDownLatch, Semaphore, CyclicBarrier 和 Exchanger 这些同步类简化了编码操作,而用wait和notify很难实现对复杂控制流的控制。
    其次,这些类是由最好的企业编写和维护在后续的JDK中它们还会不断优化和完善,使用这些更高等级的同步工具你的程序可以不费吹灰之力获得优化。
  4. 多用并发集合少用同步集合,这是另外一个容易遵循且受益巨大的最佳实践,并发集合比同步集合的可扩展性更好,所以在并发编程时使用并发集合效果更好。 如果下一次你需要用到map,你应该首先想到用ConcurrentHashMap

单例模式的双检锁是什么?

这个问题在Java面试中经常被问到,但是面试官对回答此问题的满意度仅为50%。一半的人写不出双检锁还有一半的人说不出它的隐患和Java1.5是如何对它修正的。它其实是一个用来创建线程安全的单例的老方法,当单例实例第一次被创建时它试图用单个锁进行性能优化,但是由于太过于复杂在JDK1.4中它是失败的。

如何在Java中创建线程安全的Singleton?

这是上面那个问题的后续,如果你不喜欢双检锁而面试官问了创建Singleton类的替代方法,你可以利用JVM的类加载和静态变量初始化特征来创建Singleton实例,或者是利用枚举类型来创建Singleton。

如果同步块内的线程抛出异常会发生什么?

这个问题坑了很多Java程序员,若你能想到锁是否释放这条线索来回答还有点希望答对。无论你的同步块是正常还是异常退出的,里面的线程都会释放锁,所以对比锁接口我更喜欢同步块,因为它不用我花费精力去释放锁,该功能可以在finally block里释放锁实现。

多线程中的忙循环是什么?

忙循环就是程序员用循环让一个线程等待,不像传统方法wait(), sleep() 或 yield() 它们都放弃了CPU控制,而忙循环不会放弃CPU,它就是在运行一个空循环。这么做的目的是为了保留CPU缓存,在多核系统中,一个等待线程醒来的时候可能会在另一个内核运行,这样会重建缓存。为了避免重建缓存和减少等待重建的时间就可以使用它了。

Java线程池中submit() 和 execute()方法有什么区别?

两个方法都可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中, 而submit()方法可以返回持有计算结果的Future对象,它定义在ExecutorService接口中,它扩展了Executor接口,其它线程池类像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有这些方法

如果你提交任务时,线程池队列已满。会时发会生什么?

这个问题问得很狡猾,许多程序员会认为该任务会阻塞直到线程池队列有空位。事实上如果一个任务不能被调度执行那么ThreadPoolExecutor’s submit()方法将会抛出一个RejectedExecutionException异常。

怎么检测一个线程是否拥有锁?

我一直不知道我们竟然可以检测一个线程是否拥有锁,直到我参加了一次电话面试。在java.lang.Thread中有一个方法叫holdsLock(),它返回true如果当且仅当当前线程拥有某个具体对象的锁。

Java中活锁和死锁有什么区别?

这是上题的扩展,活锁和死锁类似,不同之处在于处于活锁的线程或进程的状态是不断改变的,活锁可以认为是一种特殊的饥饿。一个现实的活锁例子是两个人在狭小的走廊碰到,两个人都试着避让对方好让彼此通过,但是因为避让的方向都一样导致最后谁都不能通过走廊。简单的说就是,活锁和死锁的主要区别是前者进程的状态可以改变但是却不能继续执行。

Java多线程中的死锁

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务,死锁的发生必须满足以下四个条件:
1 互斥条件:一个资源每次只能被一个进程使用。
2 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
4 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
避免死锁最简单的方法就是阻止循环等待条件,将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序(升序或降序)做操作来避免死锁

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值