1.构造方法能不能重写?为什么?
不能,因为构造方法不能被继承
2.switch 能用byte、long、string 吗?
* switch可作用于char byte short int及其对应的包装类
* switch不可作用于long double float boolean,包括他们的包装类。不能自动向下转型,会丢失精度
* switch中可以是字符串类型,String(jdk1.7之后才可以作用在string上)
* switch中可以是枚举类型
Java 7增强了switch语句的功能,允许switch语句的控制表达式是java.lang.String类型的变量或表达式,开始支持java.lang.String类型,但是不支持StringBuffer或StringBuilder这两种类型。
3.sleep()、yield()、wait()区别?
在这3个在Java中能够用来暂停线程的方法中,sleep()和yield()方法是定义在Thread类中,而wait()方法是定义在Object类中的
wait()和sleep()的关键的区别在于,wait()是用于线程间通信的,而sleep()是用于短时间暂停当前线程。更加明显的一个区别在于,当一个线程调用wait()方法的时候,会释放它锁持有的对象的管程和锁,但是调用sleep()方法的时候,不会释放他所持有的管程。
yield()方法和sleep()方法类似,也不会释放“锁标志”,区别在于,它没有参数,即yield()方法只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行,另外yield()方法只能使同优先级或者高优先级的线程得到执行机会,这也和sleep()方法不同。
wait和sleep的主要区别是调用wait方法时,线程在等待的时候会释放掉它所获得的monitor,但是调用Thread.sleep()方法时,线程在等待的时候仍然会持有monitor或者锁。另外,Java中的wait方法应在同步代码块中调用,但是sleep方法不需要。
另一个区别是Thread.sleep()方法是一个静态方法,作用在当前线程上;但是wait方法是一个实例方法,并且只能在其他线程调用本实例的notify()方法时被唤醒。另外,使用sleep方法时,被暂停的线程在被唤醒之后会立即进入就绪态(Runnable state),但是使用wait方法的时候,被暂停的线程会首先获得锁(译者注:阻塞态),然后再进入就绪态。所以,根据你的需求,如果你需要暂定你的线程一段特定的时间就使用sleep()方法,如果你想要实现线程间通信就使用wait()方法。
yield和sleep的主要是,yield方法会临时暂停当前正在执行的线程,来让有同样优先级的正在等待的线程有机会执行。如果没有正在等待的线程,或者所有正在等待的线程的优先级都比较低,那么该线程会继续运行。执行了yield方法的线程什么时候会继续运行由线程调度器来决定,不同的厂商可能有不同的行为。yield方法不保证当前的线程会暂停或者停止,但是可以保证当前线程在调用yield方法时会放弃CPU。
Java中sleep方法的几个注意点:
Thread.sleep()方法用来暂停线程的执行,将CPU放给线程调度器。
Thread.sleep()方法是一个静态方法,它暂停的是当前执行的线程。
Java有两种sleep方法,一个只有一个毫秒参数,另一个有毫秒和纳秒两个参数。
与wait方法不同,sleep方法不会释放锁
如果其他的线程中断了一个休眠的线程,sleep方法会抛出Interrupted Exception。
休眠的线程在唤醒之后不保证能获取到CPU,它会先进入就绪态,与其他线程竞争CPU。
有一个易错的地方,当调用t.sleep()的时候,会暂停线程t。这是不对的,因为Thread.sleep是一个静态方法,它会使当前线程而不是线程t进入休眠状态。总之,记住sleep和yield作用于当前线程。
join:一种特殊的wait,当前运行线程调用另一个线程的join方法,当前线程进入阻塞状态直到另一个线程运行结束
4.线程状态转换
线程变化的状态转换图例如以下:
1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其它线程调用了该对象的start()方法。
该状态的线程位于可执行线程池中,变得可执行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU。执行程序代码。
4、堵塞状态(Blocked):堵塞状态是线程由于某种原因放弃CPU使用权。临时停止执行。直到线程进入就绪状态,才有机会转到执行状态。
堵塞的情况分三种:
(一)、等待堵塞:执行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步堵塞:执行的线程在获取对象的同步锁时,若该同步锁被别的线程占用。则JVM会把该线程放入锁池中。
(三)、其它堵塞:执行的线程执行sleep()或join()方法,或者发出了I/O请求时。JVM会把该线程置为堵塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完成时。线程又一次转入就绪状态。
5、死亡状态(Dead):线程运行完了或者因异常退出了run()方法,该线程结束生命周期。
1、线程的实现有四种方式:一是继承Thread类,二是实现Runnable接口,三是实现Callable接口,四是线程池。但无论如何,当我们new了这个对象后。线程就进入了初始状态;
2、当该对象调用了start()方法,就进入就绪状态;
3、进入就绪状态后,当该对象被操作系统选中。获得CPU时间片就会进入运行状态;
4、进入运行状态后情况就比較复杂了
4.1、run()方法或main()方法结束后,线程就进入终止状态;
4.2、当线程调用了自身的sleep()方法或其它线程的join()方法,就会进入堵塞状态(该状态既停止当前线程,但并不释放所占有的资源)。当sleep()结束或join()结束后。该线程进入可执行状态,继续等待OS分配时间片;
4.3、线程调用了yield()方法,意思是放弃当前获得的CPU时间片,回到就绪状态,这时与其它进程处于同等竞争状态,OS有可能会接着又让这个进程进入执行状态。
4.4、当线程刚进入就绪状态(注意,还没执行),发现将要调用的资源被synchronized(同步),获取不到锁标记。将会马上进入锁池状态,等待获取锁标记(这时的锁池里或许已经有了其它线程在等待获取锁标记,这时它们处于队列状态,既先到先得),一旦线程获得锁标记后,就转入就绪状态。等待OS分配CPU时间片。
4.5、当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的全部资源,与堵塞状态不同)。进入这个状态后。是不能自己主动唤醒的,必须依靠其它线程调用notify()或notifyAll()方法才干被唤醒(因为notify()仅仅是唤醒一个线程,但我们由不能确定详细唤醒的是哪一个线程。或许我们须要唤醒的线程不可以被唤醒,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程),线程被唤醒后会进入锁池。等待获取锁标记。
5.run()和start()区别
Java的线程是通过java.lang.Thread类来实现的。VM启动时会有一个由主方法所定义的线程。可以通过创建Thread的实例来创建新的线程。每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。通过调用Thread类的start()方法来启动一个线程。
在Java当中,线程通常都有五种状态,创建、就绪、运行、阻塞和死亡:
第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个事件的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
第五是死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪。
多线程原理:相当于玩游戏机,只有一个游戏机(cpu),可是有很多人要玩,于是,start是排队!等CPU选中你就是轮到你,你就run(),当CPU的运行的时间片执行完,这个线程就继续排队,等待下一次的run()。
调用start()后,线程会被放到等待队列,等待CPU调度,并不一定要马上开始执行,只是将这个线程置于可执行状态。然后通过JVM,线程Thread会调用run()方法,执行本线程的线程体。先调用start后调用run,这么麻烦,为了不直接调用run?就是为了实现多线程的优点,没这个start不行。
1.start()方法来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行操作的, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。
2.run()方法当作普通方法的方式调用。程序还是要顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码; 程序中只有主线程——这一个线程, 其程序执行路径还是只有一条, 这样就没有达到写线程的目的。
记住:多线程就是分时利用CPU,宏观上让所有线程一起执行 ,也叫并发
6.线程和进程区别:
1. 进程和线程的简介
(1)进程的概念
1)进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
2)进程中所包含的一个或多个执行单元成为线程。进程还拥有一个私有的虚拟地址空间,该空间仅能被它所包含的线程访问。
3)线程智能属于一个进程并且它智能访问该进程所拥有的资源。当操作系统创建一个进程后,该进程会被申请一个名为主线程或首要线程的线程。
(2)线程的概念:
一个线程是进程的一个顺序执行流。同类的多个线程共享一块内存空间和一组系统资源,线程本身有一个供程序执行的堆栈。线程在切换时负荷小。因此,线程成为轻负荷进程。一个进程中可以有多个线程。
(3)进程和线程的区别:
1)地址空间:进程的各个线程,它们共享进程的地址空间,而进程有自己独立的地址空间。
2)执行速度:线程的切换速度要比进程快的多。
3)相互依赖上:进程是资源分配和拥有的单位,同一个进程内的线程共享进程资源。
4)线程是处理器调度的基本单位,但进程不是。
5)二者皆可并发执行。
(4)线程的适用场合:
适用于一个程序中需要多个任务同时执行,此时可以借助多线程来完成这个任务。