线程(二)

1、创建线程有几种方式?哪种受欢迎 为什么?

有三种方式可以创建线程:继承Thread类、实现Runnable接口、应用程序可以使用Executor框架来创建线程池
实现Runnable接口这种方式更受欢迎,因为这个不需要继承Thread类。在应用设计中已经继承了别的对象的情况下,这需要多继承,但Java不支持多继承,所以只能实现接口。同时线程池也是非常高效的,很容易实现和使用

2、Java多线程回调是什么意思?

所谓回调,就是客户程序C调用服务程序S中的某个方法A,然后S又在某个时候反过来调用C中的某个方法B,对于C来说,这个B就是回调方法。

3、列举以下启动线程有哪几种方式,线程池的种类都有哪些?

启动线程有三种方式:
一、继承Thread类创建线程类
1.定义Thread类的子类,并重写该类的run()方法,run()方法的方法体就代表了线程要完成的任务。把run()方法称为执行体。
2.创建Thread子类的实例,即创建线程对象。
3.调用线程对象的start()方法启动该线程。

package com.thread;

public class Test1 extends Thread{
	int i = 0; 
	public void run(){
	for(;i < 100;i++){
	System.out.println(getName() + " " + i);
	}
	}
	public static void main(String[] args){
	for(int i = 0; i < 100; i++){
	System.out.println(Thread.currentThread().getName() + " " "+ i);
	if(i == 20){
	new Test1().start();

	}
	}
	}
}

上述代码中Thread.currentThread()方法返回当前正在执行的线程对象。
getName()方法返回调用该方法的线程名字。
二、通过Runnable接口创建线程类
1.定义runnable接口的实现类,并重写该接口的run()方法。
2.创建Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该线程对象才是正真的线程对象。
3.调用线程对象的start()方法来启动该线程

package com.thread;

public class test2 implements Runnable{
	private int i ;
	public void run(){
	for(;i < 100;i++){
	 System.out.println(getName() + " " + i);
 	}

	}
	public static void main(String[] args){
	for(int i = 0; i < 100;i++){
	System.out.println(Thread.currentThread().getName() + " " + i);
	if(i == 20){
	test2 t = new test2();
	new Thread(t,"新线程1").start();
	new Thread(t,"新线程2").start();
	}
	}
	}
}

三、通过Callable和Future创建线程(用的较少)
1.创建Callable接口的实现类,并实现call()方法,该call()方法作为线程执行体,有返回值。
2.创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
3.使用FutureTask对象作为Thread对象的target创建并启动新线程。
4.调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。

4、Java中cyclicbarrier和countdownlatch的区别

CountdownLatch和Cyclicbarrier都能够实现线程之间的等待,但侧重点不同:
1.countDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,他才执行。
2.CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;
3.CountdownLatch是不能够重用的,而Cyclicbarrier是可以重用的。

5、线程池的优势

1.降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
2.提高响应速度。当任务到达时,任务可以不需要等到线程创建救恩那个执行。
3.提高线程的可管理性,线程是稀缺资源,如果无限的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。

6、Java中有几种线程池?并讲讲实现过程

1.newFixedThreadPool创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个线程,如果工作线程达到线程池初始化的最大数,则将提交的任务存入到池队列。
2.newCachedThreadPool创建一个可以缓存的线程池。工作线程的创建数量几乎没有限制(其实也有限制的,数目为Integer.MAX_VALUE)这样可灵活的往线程池中添加线程.如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认60秒),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
3.newSingleThreadExecutor创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个线程取代他,保证顺序执行,这是特色。单工作线程最大的特点是可保证顺序的执行各个任务,并且再任意给定的时间不会有多个线程是活动的。
4.newScheduleThreadPool创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。

7、哪些方式可以启动一个线程

1.继承自Thread类
2.实现Runnable接口
3.即实现Runnable接口,也继承Thread类,并重写run方法

8、列举一下创建线程的方法

继承Thread类需要从Java.lang.Thread类派生一个新的线程类,重载它的run方法
实现runnable接口,重载Runnable接口中的run方法
实现Runnable接口更好,使用这个方式创建的线程可以处理同一资源,从而实现资源的共享

9、AQS

AQS其实就是一个可以给我们实现锁的框架。
内部实现的关键是:先进先出的队列、state状态;定义了内部类ConditionObject拥有两种线程那个模式独占模式和共享模式;在LOCK包中的相关锁(常用的有ReentrantLock、ReadWriteLock)都是基于AQS来构建,一般我们叫AQS为同步器。

10、线程池的运行流程,使用参数及方法则略

线程池主要就是指定线程池核心线程数大小,最大线程数,存储的队列,拒绝策略,空闲线程存活时长。当需要任务大于核心线程数的时候,就开始增加线程池创建的线程数量,如果当线程数也达到最大,就开始执行拒绝策略,比如记录日志,直接丢弃,或者丢弃最老的任务

11、生产者消费模式

生产者和消费者在同一时间段内共用统一存储空间,生产者向空间里面生产数据,而消费者取走数据。
优点:支持并发,解耦。

12、实现多线程同步的方法

可以使用synchronized、lock、volatile和ThreadLocal来实现同步

13、如何在线程安全的情况下实现一个计数器

可以使用加锁,比如synchronized或者Lock,也可以使用Concurrent包下的原子类。

14、多线程中的i++线程安全否

不安全。因为i++不是原子性操作。I++分为读取I值,对I值加1,再赋值给I++,执行期中任何一步都是有能被其他线程抢占的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值