Java笔记

基本知识

引用和对象

  • 新建一个对象
class Tank {
    int level;
}

public class Assignment {
    public static void main(String[] args) {
        Tank t1=new Tank();
        Tank t2=new Tank();
        t1.level=9;
        t2.level=47;
    }
}
  • 引用在赋值,对象不赋值
t1=t2; 
//此时t1.level=t2.level=47

t1.level=27; 
//此时t1.level=t2.level=27
//因为t1和t2都是同一个对象的引用了

基本数据类型

  • 其它数据类型不能自动转换为boolean
int a=1;
if(a) { //illegal!

}

enum

public enum VIPClass {
	BRONZE,SILVER,GOLD,DIAMOND;
}

private VIPClass vipClass=VIPClass.DIAMOND;

String

int length(); //返回字符串长度
char charAt(int i); //返回索引位置的字符
char[] getChars(int start,int end); 
byte[] getBytes(int start,int end);
boolean equals(String s); //字符串的比较不能用==
int indexOf(char c); //返回c在字符串中的位置,如果没有返回-1
String subString(int start,int end); //获取字串(不包含end)

初始化

基本数据类型初始化

  • 如果没有赋初值,Java会自动为其赋为默认值,如整型为0

构造器初始化

  • 每个类有一个默认的无参构造器,但如果声明了有参的构造器,Java不会帮你再生成默认的无参构造器

静态数据的初始化

static String str1="hello";

static String str2;
static{
	str2="world";
}

数组的初始化

String[] s1=new String[10];
String[] s2=new String[] {};
String[] s3=new String[] {"hello","world"};
String[] s4=new String[] {new String("hello"),new String("world")};

控制执行流程

  • for-each语法

import java.util.*;

Random rand=new Randon(47); 
//47是种子,种子一样,生成的随机数也一样
//无参会使用系统当前的时间作为种子

int r[]=new int[10];
for(int i=0;i<10;i++) {
    r[]=rand.nextInt(26); //生成0-26之间(不含26)的随机整数
}

//不需要知道x是r数组中的第几个时,可以用for-each语法
for(int x:r) {
    System.out.println(x);
}
  • 输出指定个数的斐波那契数列
int fibonacci(int n) {
    if(n==1||n==2)
		return 1;
	else
		return fibonacci(n-1)+fibonacci(n-2); //递归
}

for(int i=1;i<=n;i++) //n是指定个数
	System.out.print(fibonacci(i)+" ");
  • 输出4位数的吸血鬼数字
int vam[]=new int[4]; //存储四位数
boolean vampire(int m,double a,double b,int i,int j) { //判断是否为吸血鬼数字
	int k=(int)b%10;
	int l=(int)b/10;
	for(int p=0;p<4;p++) {
		if(vam[p]==k&&p!=i&&p!=j)
			for(int q=0;q<4;q++)
				if(vam[q]==l&&q!=i&&q!=j&&q!=p) {
					System.out.println(m+"="+(int)a+"*"+(int)b);
					return true;
				}
	}
	return false;
}

double a,b;
for(int m=1001;m<10000;m++) { //遍历所有四位数
	boolean isVamp=false;
	if(m%100==0) //100的整数倍肯定不是
		continue; //Java不允许if里什么也不写
	int m2=m;
	for(int i=0;i<4;i++) { //将四位数每一位拆开
		vam[i]=m2%10;
		m2=m2/10;
	}
	for(int i=0;i<4;i++) { //随机组合
		for(int j=i+1;j<4;j++) {
			if(j==i)
				continue;				
            if(vam[j]!=0) {
				a=vam[i]+vam[j]*10;
				b=m/a;
				if((int)b==b) {
					isVamp=vampire(m,a,b,i,j);
					if(isVamp)
						break;
					}
			}
			if(vam[i]!=0) {
				a=vam[j]+vam[i]*10;
				b=m/a;
				if((int)b==b) {
					isVamp=vampire(m,a,b,i,j);
					if(isVamp)
						break;
				}
			}
			if(isVamp)
				break;
		}
		if(isVamp)
			break;
	}
}

封装性

访问权限

privatefriendlyprotectedpublic
同一类
同一文件
同一文件夹
其他子类
其它类

单例模式

private static View instance; //只有一个实例化对象
public static View getInstance() {
	if (instance==null) {
		instance = new View();
	} //第一次调用时才创建
	return instance;
}

继承性

继承与组合

  • 组合:在类里直接声明某个类的对象 ➡️更看重功能
  • 继承:继承自父类 ➡️更看重接口,可以重载父类的方法

继承与重载

class Cleanser{
	private String s="Cleanser";
	public void append(String a) {
		s+=a;
	}
	public void scrub() {
		append(" scrub");
	}
	public void dilute() {
		append(" dilute");
	}
	@Override
	public String toString() { //重载object函数
		return s;
	}
	public static void main(String[] args) {
		Cleanser c=new Cleanser();
		c.scrub();
		System.out.println(c);
	}
}

class Detergent extends Cleanser{
	@Override
	public void scrub() { //覆盖父类函数
		append(" Detergent.scrub()");
		super.scrub(); //调用父类函数
	}
	public static void main(String[] args) { 
		//在public类以外的类也可以有main函数,但如果不在public类的main函数中调用就不会运行
		Detergent d=new Detergent();
		d.scrub();
		d.dilute();
		System.out.println(d);
		System.out.println("Testing base class:"); //测试父类
		Cleanser.main(args); //调用其他类里的main函数
	}
}

public class Sterilizer extends Detergent{
	@Override
	public void scrub() { //覆盖父类
		append(" Sterilizer.scrub()");
		super.scrub(); //调用父类函数
	}
	public void sterilize() { //增加新的函数
		append(" Sterilizer.sterilize()");
	}
	public static void main(String[] args) {
		Sterilizer s=new Sterilizer();
		s.scrub();
		s.sterilize();
		System.out.println(s);
		System.out.println("Testing base class:"); //测试父类
		Detergent.main(args); //调用其他类里的main函数
	}
}

初始化

  • 如果父类有有参构造器,在子类的构造函数中需要初始化父类
class Code{
	private int co;
	Code(int i){
		System.out.println("Code constructor "+i);
		co=i;
	}
	protected void showCode() {
		System.out.println("The code is "+co);
	}
}

class Encrypting extends Code{
	Key k=new Key(1);
	Encrypting(){
		super(1); //父类有有参构造函数,这里必须要初始化父类
		System.out.println("Encrypting constructor ");
	}
	Encrypting(int i){
		super(i);
		System.out.println("Encrypting constructor "+i);
	}
	void printCode() {
		showCode();
	}
}

初始化顺序

  • 静态初始化
  • 动态初始化
  • 构造器初始化
class Insect{
	private int i=9;
	protected int j;
	Insect(){
		System.out.println("Insect constructor");
		System.out.println("i="+i+",j="+j);
		j=39;
	}
}

class Beetle extends Insect{
	private int k=47;
	Beetle(){
		System.out.println("Beetle constructor");
		System.out.println("j="+j+",k="+k);
	}
}

public class Crustacea extends Beetle{
	private int l=23;
	Crustacea(){
		System.out.println("Crustacea constructor");
		System.out.println("l="+l);
	}
	public static void main(String[] args) {
		Crustacea c=new Crustacea();
	}
}

/*
Insect constructor
i=9,j=0
Beetle constructor
j=39,k=47
Crustacea constructor
l=23
*/

代理

  • 暴露类中的全部或部分方法
//使用代理的方法
public class Sterilizer{
	//要定义成员,因为没有继承到父类的s
	private String s="Sterilizer";
	@Override
	public String toString() { //重载object函数
		return s;
	}
	private Detergent d=new Detergent(); //代理
	public void scrub() {
		d.scrub();
		System.out.println(d);
	}
	public static void main(String[] args) {
		Sterilizer s=new Sterilizer();
		s.scrub();
		// s.dilute(); 非法,因为通过代理方式,没有暴露出Detergent中的这个函数
		System.out.println(s);
		System.out.println("Testing base class:"); //测试父类
		Detergent.main(args); //调用其他类里的main函数
	}
}

finally关键字

  • 无论发生什么事,都要执行finally中的代码
//请以此例再次熟悉初始化顺序

class Component1{
	Component1(){
		System.out.println("Component1 constructor");
	}
	void dispose() {
		System.out.println("Erasing Component1");
	}
}

class Component2{
	Component2(){
		System.out.println("Component2 constructor");
	}
	void dispose() {
		System.out.println("Erasing Component2");
	}
}

class Component3{
	Component3(){
		System.out.println("Component3 constructor");
	}
	void dispose() {
		System.out.println("Erasing Component3");
	}
}

class Root{
	Component1 c1=new Component1();
	Component2 c2=new Component2();
	Component3 c3=new Component3();
	Root(){
		System.out.println("Root constructor");
	}
	void dispose() {
		System.out.println("Erasing Root");
	}
}

public class Stem extends Root{
	Stem(){
		System.out.println("Stem constructor");
	}
	void dispose() {
		System.out.println("Erasing Stem");
		super.dispose();
	}
	Component1 c1=new Component1();
	Component2 c2=new Component2();
	Component3 c3=new Component3();
	public static void main(String[] args) {
		Stem s=new Stem();
		try {
			System.out.println("Trying method");
		} finally {
			s.dispose();
		}
	}
}

/*
//先初始化root的成员
Component1 constructor
Component2 constructor
Component3 constructor
Root constructor

//先初始化stem的成员
Component1 constructor
Component2 constructor
Component3 constructor
Stem constructor

Trying method
//垃圾回收
Erasing Stem
Erasing Root
*/

向上转型

  • 子类对象充当父类的引用
public static void tuneAll(Instrument[] e) {
	for(Instrument i:e) //for each
		tune(i);
}

public static void main(String[] args) {
	Instrument[] orchestra= { //父类引用=子类对象
			new Wind(),
			new Percussion(),
			new Stringed(),
			new Brass(),
			new WoodWind(),
			new Piano()
	};
	tuneAll(orchestra); //向上转型
	for(Instrument o:orchestra)
		System.out.println(o);
}

多态性:接口

抽象类

  • 没有方法体
  • 不能声明具体对象
  • 如果子类还没有声明具体实现,那还是抽象类
abstract class Test{
	Test(){
		print();
	}
	public abstract void print();
}

class ExportTest extends Test{
	private int i=1;
	ExportTest(){
		System.out.println("ExportTest constructor");
	}
	public void print() {
		System.out.println(i);
	}
}

public class Excercise9 {
	public static void main(String[] args) {
		// Test t=new Test(); illegal!
		ExportTest et=new ExportTest();
		et.print();
		//先调用基类的构造器,但基类的print是抽象方法,转而调用导出类的print
	}
}

接口

  • 变量自动是static&final
  • 方法自动是public,都没有具体实现
  • 不能声明具体对象,但可以声明引用
nterface Playable{
	void play(Note n); 
}

interface Instrument{
	int VALUE=5; //static&final;
	//cannot have method definitions:
	void adjust(); //automatically public
}

class Wind implements Instrument,Playable{
	public void play(Note n) {
		System.out.println(this+".play() "+n);
	}
	@Override
	public String toString(){
		return "Wind";
	}
	public void adjust() {
		System.out.println(this+".adjust()");
	}
}

public class Music {
	static void tune(Playable p) {
		p.play(Note.MIDDLE_C);
	}
	static void tuneAll(Playable[] e) {
		for(Playable i:e)
			tune(i);
	}
	public static void main(String[] args) {
		Playable[] orchestra= { //可以声明接口的引用
				new Wind(),
				new Percussion(),
				new Stringed(),
				new Brass(),
				new Woodwind()
		};
		tuneAll(orchestra);
	}
}

适配器

  • 实现接口需要实现接口中所有的方法
  • 使用适配器可以只重载部分方法

多重继承 

  • 可以继承任意多个接口
  • 接口之间也可以任意继承

接口与工厂

  • 可以将某个实现替换为另一个实现(类似模版)
  • 利用工厂实现抛硬币和掷骰子的功能
interface Play {
	void game();
}

interface PlayFactory {
	Play getPlay();
}

class FlipTheCoin implements Play {
	@Override
	public void game() {
		System.out.println("Flip a coin!");
		for(int i=1;i<=10;i++)
			flip();
	}
	public void flip() {
		Random rand=new Random();
		switch(rand.nextInt(2)) {
		case 0:
			System.out.println("Upper side!");
			break;
		case 1:
			System.out.println("Down side!");
			break;
		}
	}
}

class RollTheDice implements Play {
	@Override
	public void game() {
		System.out.println("Roll a dice!");
		for(int i=1;i<=10;i++)
			roll();
	}
	public void roll() {
		Random rand=new Random();
		System.out.println(rand.nextInt(6)+1);
	}
}

class CoinFactory implements PlayFactory {
	@Override
	public Play getPlay() {
		return new FlipTheCoin();
	}
}

class DiceFactory implements PlayFactory {
	@Override
	public Play getPlay() {
		return new RollTheDice();
	}
}

public class Games {
	public static void gamePlayer(PlayFactory fact) {
		Play p=fact.getPlay();
		p.game();
	}
	public static void main(String[] args) {
		gamePlayer(new CoinFactory());
		gamePlayer(new DiceFactory());
	}
}

内部类

  • 定义在另一个类中的类,叫做内部类
  • 内部类可以访问外部类的所有

创建和访问内部类

public class Outer {
    class Inner {}
    public Inner getInner(){ //动态方法中可以随便构造内部类对象
        return new Inner();
    }
    public static void main(String[] args) { //静态方法中构造内部类对象
        Outer o=new Outer(); //必须先构造外部类对象
        Outer.Inner i1=o.getInner(); //调用类内的动态方法
        Outer.Inner i2=o.new Inner(); //直接创建
    }
}

匿名内部类

public interface Inner { //接口
    int value();
}

public class Outer {
    public Inner inner() { //创建一个实现Inner的匿名类的对象
        return new Inner() {
            public int value(){}
        }
    }
    public static void main(String[] args) {
        Outer o=new Outer(); 
        Inner i=o.inner();
    }
}

容器

Collection

List

  • 可以自动扩容
  • ArrayList: 数组,便于随机访问元素,但插入和删除较慢
  • LinkedList: 链表,便于插入和删除,但随机访问较慢
class ListFeatures {
	public static void main(String[] args) {
		Random rand=new Random(47);
		List<Integer> ints=new ArrayList<Integer>(7);
		for(int i=10;i<17;i++)
			ints.add(i);
		System.out.println("1: "+ints);
		ints.add(7); //自动扩容
		System.out.println("2: "+ints);
		System.out.println("3: "+ints.contains(7)); //是否包含某个数据
		ints.remove(7); //删除数据
		int t=ints.get(2); //获取列表中的下标为2的数据
		System.out.println("4: "+t+" "+ints.indexOf(t)); //返回某个数据在列表中的下标
		System.out.println("5: "+ints.remove(2)); //删除链表中下标为2的数据
		System.out.println("6: "+ints);
		ints.add(3,9); //在下标为3的位置插入元素9
		System.out.println("7: "+ints);
		List<Integer> sub=ints.subList(1, 4); //获取下标为1-4的数据形成子列(不含4)
		System.out.println("8: Sublist: "+sub);
		System.out.println("9: "+ints.containsAll(sub)); //返回是否包含子列中的所有元素
		Collections.sort(sub); //按照升序整理子列
		System.out.println("10: Sorted sub: "+sub); 
		System.out.println("11: "+ints.containsAll(sub)); //该函数与顺序无关
		Collections.shuffle(sub,rand); //随机排列列表
		System.out.println("12: Suffled sub: "+sub);
		System.out.println("13: "+ints.containsAll(sub));
		List<Integer> copy=new ArrayList<Integer> (ints); //生成副本
		sub=Arrays.asList(ints.get(1),ints.get(4)); //获取下标为1、4的数据生成列表
		System.out.println("14: Sub: "+sub);
		copy.retainAll(sub); //取交集
		System.out.println("15: Copy: "+copy);
		copy=new ArrayList<Integer> (ints); //重新生成副本
		copy.remove(2);
		System.out.println("16: "+copy);
		copy.removeAll(sub); //删除包含子列的数据
		System.out.println("17: "+copy);
		copy.set(1, 23); //将下标为1的数据设置成23
		System.out.println("18: "+copy);
		copy.addAll(2,sub); //从下标为2的数据开始,插入子列
		System.out.println("19: "+copy);
		System.out.println("20: "+ints.isEmpty()); //返回列表是否为空
		ints.clear(); //清除所有数据
		System.out.println("21: "+ints);
		System.out.println("22: "+ints.isEmpty());
		ints.addAll(sub); //将子列中所有数据加入
		System.out.println("23: "+ints);
	}
}

Stack

//+压栈,-弹出
String s="+U+n+c---+e+r+t---+a-+i-+n+t+y---+-+r+u--+l+e+s---";
Stack<Character> stack=new Stack<>();
for(int i=0;i<s.length();i++){
	if(s.charAt(i)=='+')
		stack.push(s.charAt(++i));
	else
		System.out.print(stack.pop()+" ");
}

Set

不存在重复的对象

//统计输入的元音字母的总和
public class UniqueWords {
	public static void main(String[] args) {
		Set<Character> unique=new HashSet<Character>();
		unique.add('a');
		unique.add('e');
		unique.add('i');
		unique.add('o');
		unique.add('u');
		unique.add('A');
		unique.add('E');
		unique.add('I');
		unique.add('O');
		unique.add('U');
		BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
		String s=null;
		try { 
			System.out.println("Please input a sentence!");
			s=in.readLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
		int count=0;
		for(int i=0;i<s.length();i++) {
			Iterator<Character> it=unique.iterator(); //注意迭代器的声明要放在这里,才可以每次都重新指向第一个
			for(int j=0;j<unique.size();j++) {
				if(s.charAt(i)==it.next()) //通过迭代器获取HashSet中的元素
					count++;
			}
		}
		System.out.println("There are "+count+" unique words in this sentence.");
	} 
}

Queue

Random rand=new Random();
PriorityQueue<Double> pq=new PriorityQueue<>();
for(int i=0;i<10;i++)
	pq.offer(rand.nextDouble());
System.out.println(pq);
for(int i=0;i<10;i++)
	pq.poll();
System.out.println(pq);

Iterator

单向移动

class RandomRodentGenerator { //啮齿类动物生成器
	private Random rand=new Random(); //随机数
	public Rodent next() {
		switch(rand.nextInt(3)) {
			default:
			case 0:
				return new Mouse();
			case 1:
				return new Gerbil();
			case 2:
				return new Hamster();
		}
	}
}

ArrayList<Rodent> rodents=new ArrayList<Rodent>();
for(int i=0;i<9;i++) 
	rodents.add(gen.next());
Iterator<Rodent> it=rodents.iterator(); //迭代器
while(it.hasNext()) { //序列中还有下一个
	Rodent ro=it.next(); //获取下一个元素
	ro.bite();
    //迭代器自动向前移动一个位置
}

ListIterator

双向移动

//把序列1的元素反序插入序列2
List<Integer> i1=new ArrayList<Integer>(8);
for(int i=0;i<8;i++)
	i1.add(i);
List<Integer> i2=new ArrayList<Integer>(8);
ListIterator<Integer> it=i1.listIterator(8); //从最后一个位置开始
while(it.hasPrevious()) { //如果有前一个元素
	Integer i=it.previous();
	i2.add(i);
}

Map

  • 储存健值对 key&value,类似关联数组 

ArrayList<Gerbil> gerbils=new ArrayList<>();
for(int i=1;i<=3;i++)
	gerbils.add(new Gerbil(i));
Map<String,Gerbil> m=new HashMap<>();
String[] str= {"Catherine", "Ann", "Elizabeth"};
for(int i=0;i<3;i++)
	m.put(str[i], gerbils.get(i)); //将元素放入Map
System.out.println(m);
Set<String> set=m.keySet(); //获取Set的key
Iterator<String> it2=set.iterator(); //创建迭代器
while(it2.hasNext()) {
	String key=it2.next();
	System.out.println(m.get(key)); //通过key找到Map中的元素
	m.get(key).hop();
}

I/O流

File

new File(String path); //创建一个文件对象
boolean exist(); //是否存在
boolean isFile(); //是文件吗
boolean isDirectory(); //是文件夹吗
String getName(); //获取文件名
String getPath(); //获取文件路径
long length(); //文件长度
boolean canRead(); //可读吗
boolean canWrite(); //可写吗
String[] list(); //目录中的文件
boolean renameTo(File newFile); //相当于新建一个文件
boolean delete(); //删除文件
boolean mkdir(); //在当前位置创建一个文件夹
boolean mkdirs(); //在当前位置创建多层文件夹
public class Excercise18 {
	static int countDir=0,countFile=0;
	static double size=0;
	public static void main(String[] args) {
		File f=new File("/Users");
		getFile(f);
		System.out.println("There are "+countDir+" directories."); //输出文件夹数目
		System.out.println("There are "+countFile+" files."); //输出文件总数
		getSize(); //输出文件尺寸大小
	}
	public static void getFile(File f) { //递归函数
		if(f.isFile()) { //如果是文件
			countFile++;
			size+=f.length();
		}
		if(f.isDirectory()) { //如果是文件夹
			countDir++;
			File[] files=f.listFiles(); //获取文件夹下的所有文件或文件夹
			for(File temp:files) { //遍历,递归
				getFile(temp);
			}
		}
	}
	public static void getSize() { //把计算出来的尺寸(B)转化为合适的单位
		String[] s=new String[]{"B","KB","MB","GB"};
		int mark=0;
		while(size>1024&&mark<4) { //选取合适的单位,最大单位到GB
			size/=1024;
			mark++;
		}
		DecimalFormat df=new DecimalFormat("#.00"); //保留两位小数
		System.out.println("The total size is "+df.format(size)+s[mark]);
	}
}

 FilenameFilter

class DirFilter implements FilenameFilter {
    public boolean accept(File dir) {
        ...
        if(name.endsWith(".pdf")))
            return true;
        else
            return false;
    }
}

输入输出

读入文件

public static String read(String name) throws IOException {
	BufferedReader in=new BufferedReader(new FileReader(name));
	String s;
	StringBuilder sb=new StringBuilder();
	while((s=in.readLine())!=null) {
		sb.append(s+"\n");
	}
	in.close();
	return sb.toString();
}

public static void main(String[] args) throws IOException {
	System.out.println(read("file path"));
}

写入文件

public static void main(String[] args) throws IOException {
	BufferedReader in=new BufferedReader(new StringReader(Excercise18.read("file path"))); //刚刚写的read函数
	PrintWriter out=new PrintWriter("Excercise18.out");
	int lineCount=1; //记录行数
	String s;
	while((s=in.readLine())!=null) {
		out.println(lineCount++ +":"+s);
	}
	out.close();
    System.out.println(Excercise18.read("Excercise18.out")); //在命令行输出
	FileOutputStream fos = new FileOutputStream("new file path"); //新建文件
	byte[] content=read("file path").getBytes(); //把要写入的内容转化为byte
	fos.write(content); //写入
	fos.close();
    //从doc这类文件读和写的时候,中文都会变成乱码(因为Java一处编写、处处运行的特点)
}

从命令行中读取

//从命令行获取输入
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
try {
	String line;
	line=in.readLine();
} catch (IOException e) {
	e.printStackTrace();
}

多线程

建立线程

实现Runnable接口

public class LiftOff implements Runnable {
    public void run() {
        while(true) {
            ......
        }
    }
    Thread t=new Thread(new LiftOff());
    t.start();
}

继承Thread类

class SimpleThread extends Thread {
    public void run() {
        while(true) {
            ......
        }
    }
}

new SimpleThread().start();

//匿名内部类的形式
public class Test {
    new Thread() {
        public void run() {
            while(true) {
                ......
            }
        }
    }.start();
}

使用Executor(线程池)

public class CachedThreadPool {
    public static void main(String[] args) {
        ExecutorService exec=Executors.newCachedThreadPool(); //创建线程池
        for(int i=0;i<5;i++){ //给每个任务分配一个线程
            exec.execute(new LiftOff()); //Runnable的实现类
        }
        exec.shutdown();
    }
}
//可以自动扩容的线程池
ExecutorService exec1=Executors.newCachedThreadPool(); 

//指定数量的线程池,如果线程超过5,后面的任务需要等待
ExecutorService exec2=Executors.newFixedThreadPool(5); 

//单线程
ExecutorService exec3=Executors.newSingleThreadPool(); 

 从任务中返回值

class TaskWithResult implements Callable<String> { //实现一个泛型接口
    private int id;
    public TastWithResult(int id) {
        this.id=id;
    }
    public String call() {
        return "result of TaskWithResult"+id;
    }
}

public class CallableDemo {
    public static void main(String[] args) {
        ExecutorService exec=Executors.newCachedThreadPool();
        ArrayList<String> results=new ArrayList<>;
        for(int i=0;i<10;i++) {
            results.add(exec.submit(new TaskWithResult(i)));
        }
        for(String s:results) {
            try {
                System.out.println(s.get()); //这时线程可能还没执行完
            } catch(Exception e) {
                System.out.println(e);
            } finally {
                exec.shutdown();
            }
        }
    }
}

加入一个线程

等到Sleeper线程结束,Joiner线程才会继续进行

class Sleeper extends Thread {
    public void run() {
        sleep(1000); //休眠,以毫秒为单位
    }
}

class Joiner extends Thread {
    Sleeper s;
    Joiner (Sleeper s) {
        this.s=s;
    }
    public void run() {
        s.join();
        System.out.println("wake up");
    }
}

 锁

多线程可以共用一把锁,当有线程要执行时,它获取锁,并且上锁,其他线程要执行时,看到上锁了,就挂起,等待上锁的线程使用完毕释放锁,其他的线程才能继续进行。

class Meal {
    ......
}

class Waiter implements Runnable {
    private Restaurant r;
    public Waiter(Restaurant r) {
        this.r=r;
    }
    public void run() {
        try {
            while(!Thread.interrupted() {
                synchronized(this) {
                    while(r.meal==null)
                        wait();
                }
            }
        } catch(InterruptedException e){
            System.out.println("Waiter interrupted");
        }
        synchronized(r.chef) {
            r.meal=null;
            r.chef.notifyAll();
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值