1.线程和进程的联系和区别是什么?
进程是执行中的一个程序,是动态的概念。是系统分配资源的基本单位。
线程是CPU执行和调度的基本单位。
一个进程可以有多个线程。
2.什么是前台线程,什么是后台线程?
主线程main结束后,还有前台线程在运行,程序就不结束,而只有后台线程在运行,程序就结束了。
main结束后后台线程还在继续运行,后台线程在应用程序结束后都会自动结束。
3.创建线程有几种方法?他们之间的区别是什么?
两种。
1)继承Thread类。
2)实现Runnable接口。
区别在于调用start方法时,后者还要多new一个Thread对象来调用start().
//继承Thread类
class A extends Thread{
public void run(){};
}
//实现Runnable接口
class B implements Runnable{
public void run(){};
}
psvm
public static void main(String arg[]){
//继承Thread类
A a = new A();
A.start();
//实现Runnable接口
B b = new B();
new Thread(b).start();
}
4.线程的生命周期有哪些状态?可以用什么方法来该改变这些状态?
创建,可运行,运行中,堵塞,死亡。
sleep(),wait():可以让该线程进入死亡状态。在wait的线程需要notifyAll()来唤醒才能继续执行。
5.什么是线程安全?为什么会产生线程安全问题?如何解决线程安全问题?
线程安全:线程安全的代码会保证多个线程正确且正常地执行,不会导致数据污染等问题。
为什么会产生线程安全问题:两个线程调用同一个对象的同一方法,比如一个对象的i值为10,它的值还没有变,还没有走到i--这一步,系统切换到了另一个对象它的i值也为10.这样二者的值就重复了。或者对于一个i>0的要求。两个对象都看到了i=1,一个对象抢到了i=1,sleep进入休眠,cpu切换到另一个对象,i还没有变化,这个对象的i也等于1.最后都进行了i--的操作,i值就变为了-1.
如何解决线程安全问题:
同步方法:给方法加上synchronized,使得这个方法执行完,cpu才切换给另一个线程。
同步块:synchronized(obj){};本质锁的是obj这个对象
6.什么是线程的同步通信?同步通信又是如何实现的?
线程同步通信:线程同步通信是希望实现两个或多个线程之间的某种制约关系
实现:两个线程之间得同步通讯,需要方法前的synchronized,变量前的volatile,方法中的wait和notify,还有布尔型变量指示器,他们之间的种种配合才能实现线程的同步通讯。
7.什么是死锁?
两个以上对象相互竞争资源而导致的争执不下的局面,比如A需要B的资源才能往下走,B也需要A的资源才能往下走,互不让步,形成僵局。
8.FutureTask类有什么作用?它实现了哪些接口?Callable接口和Runnable接口有什么不同?
可以让程序员准确的知道线程什么时候执行完成并获得线程执行完成后的结果。
实现了Runnable和Callable接口.
- Callable可以返回一个类型V,而Runnable不可以
- Callable能够抛出checked exception,而Runnable不可以。
- Runnable是自从java1.1就有了,而Callable是1.5之后才加上去的
- Callable和Runnable都可以应用于executors。而Thread类只支持Runnable.
9.volatile关键字有什么作用?举例说明。
指示JVM这个变量是不稳定的,每次使用它都要到主存中进行读取.让共享变量具有可见性和有序性。
可见性:多个线程共享一个对象,当一个线程改变一个对象的值的时候,其他对象能够看到。
有序性:按照代码的顺序进行。
原子性:一个或者一组操作要么全部执行要么不执行。
class test{
boolean volatile flag = true;
private void A() {flag = false};
public void B(){
while(flag){};
}
}
//volatile就可以令线程A执行了A方法后修改flag为false,切换线程,
//线程B执行B方法时就不会进入到while循环里了
10.模拟Java程序编写烧水泡茶最优工序.
package FutureTask源码;
import java.util.Date;
//烧水10min 洗茶杯5in.最后泡茶
public class Tea implements Runnable{
@Override
public void run() {
System.out.println("泡茶中。。。");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("泡茶结束。。。");
}
public static void main(String[] args) {
ShaoShui ss = new ShaoShui();
WashingCup wc = new WashingCup();
Tea tea = new Tea();
Thread t1 = new Thread(ss);
Thread t2 = new Thread(wc);
Thread t3 = new Thread(tea);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
t3.start();
}
}
class ShaoShui implements Runnable{
static Date date = new Date();
@Override
public void run() {
int count = 10;
while(count!=0){
System.out.println(date+"烧水中...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
}
System.out.println("烧水结束");
}
}
class WashingCup implements Runnable{
static Date date = new Date();
@Override
public void run() {
int count = 5;
while(count!=0){
System.out.println(date+"洗茶杯中...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
}
System.out.println("洗茶杯结束");
}
}
11.编写一个基于多线程的生产者/消费者Java应用,各产生10个生产者和消费者线程,共享一个缓冲区队列(长度自设),生产者线程将产品放入到缓冲区,消费者线程从缓冲区取出产品。
package 多线程;
//notifyAll():唤醒 当前等待的线程
//wait():让当前执行的线程等待
public class TestPC {
public static void main(String[] args) {
SynContainer synContainer = new SynContainer();
Producer producer = new Producer(synContainer);
Consumer consumer = new Consumer(synContainer);
producer.start();
consumer.start();
}
}
//生产者
class Producer extends Thread{
SynContainer synContainer;
public Producer(SynContainer synContainer){
this.synContainer = synContainer;
}
@Override
public void run() {
super.run();
//生产100只鸡
for (int i = 1; i < 100; i++) {
synContainer.push(new Chicken(i));
System.out.println("生产了第"+i+"只鸡");
}
}
}
//消费者
class Consumer extends Thread{
SynContainer synContainer;
public Consumer(SynContainer synContainer){
this.synContainer = synContainer;
}
@Override
public void run() {
super.run();
for (int i = 0; i < 100; i++) {
System.out.println("消费者吃了第"+synContainer.pop()+"只鸡");
}
}
}
//食物
class Chicken{
int id;
public Chicken(int id){
this.id = id;
}
}
//缓冲区
class SynContainer{
Chicken chickens[] = new Chicken[10];
int count = 0;//存放目前的产品数量
//生产产品
public synchronized void push(Chicken chicken) {
//如果数量满了就可以通知消费者消费了
if(count == chickens.length){
try {
this.wait(); //等待消费者消费
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//否则就开始生产产品
chickens[count++] = chicken;
this.notifyAll();//通知消费者消费了
}
//消费者消费,并返回消费的鸡的id
public synchronized int pop() {
if(count == 0){
//没鸡了要通知生产者生产了
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Chicken chicken = chickens[--count];
//通知生产者生产了
this.notifyAll();
return chicken.id;
}
}