java线程(笔试用)

  • 启动线程两种方式

继承Thread类

new Thread() {
    public void run() {

    }
}.start();

实现Runnable接口

new Thread(new Runnable() {
    public void run() {

    }
}).start();

 

  • 线程互斥

多个线程操作同一个资源(即某个对象),为保证线程在对资源的状态(即对象的成员变量)进行一些非原子性操作后,状态仍然是正确的。

两种方法解决:

加入互斥代码块synchronized (lock){}

方法前加synchronized关键字

 

  • 线程同步

使用wait、notifynotifyAll方法实现

要用到共同数据(包括同步锁)或相同算法的多个方法要封装在一个类中
锁是上在代表要操作的资源类的内部方法中的,而不是上在线程代码中的。这样写出来的类就是天然同步的,只要使用的是同一个new出来的对象,那么这个对象就具有同步互斥特性
判断唤醒等待标记时使用while增加程序健壮性,防止伪唤醒

典型是生产者消费者例子,生产和消费方法交替进行:

public class ProducerConsumer {
	public static void main(String[] args) {
		final ProducerConsumer pc = new ProducerConsumer();
		
		for(int i=0;i<5;i++){
			new Thread() {   
			    public void run() {   
			    	while(true){
			    		try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
			    		pc.produce();
			    	}
			    }   
			}.start();  
		}
		for(int i=0;i<5;i++){
			new Thread() {   
			    public void run() {
			    	while(true){
			    		try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
			    		pc.consume();
			    	}
			    }   
			}.start();  
		}
	}
	
	private boolean flg = true;
	public synchronized void produce(){
		while(!flg){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("produce");
		flg = false;
		this.notify();
	}
	public synchronized void consume(){
		while(flg){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("consume");
		flg = true;
		this.notify();
	}
}

 

  • 多个线程访问共享数据的方式

1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据。

2.如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,有如下两种方式来实现这些Runnable对象之间的数据共享:

    a.将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个Runnable对象。每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行的各个操作的互斥和通信。

    b.将这些Runnable对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部类的这些方法。
    c.上面两种方式的组合:将共享数据封装在另外一个对象中,每个线程对共享数据的操作方法也分配到那个对象身上去完成,对象作为这个外部类中的成员变量或方法中的局部变量,每个线程的Runnable对象作为外部类中的成员内部类或局部内部类。
    总之,要同步互斥的几段代码最好是分别放在几个独立的方法中,这些方法再放在同一个类中,这样比较容易实现它们之间的同步互斥和通信。

 

  • ThreadLocal

ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。

当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

你可能感兴趣的:(经验总结,java)