线程基础

线程基本概念

1.什么是进程? -正在执行的程序
2.什么是线程? - 一个能够完成独立功能的执行路径,一个进程可有多个线程
3.为什么需要开启多线程?

  • a. 当执行某些耗时操作的任务的时候需要开启多线程,防止线程阻塞
  • b. 能够让两个任务看起来像是在同时执行
  • c. 提高CPU的使用率,进而提高进程和内存的使用率(当键盘在输入的时候,main无法进行其他操作,一直等待输入操作完成,才执行之后的操作,内存使用率不高)
  • 4.为什么开启多线程会同时执行? - 因为CPU切换执行的速度太快了,肉眼无法察觉
  • 5.开启多线程是不是越多越好,提高了效率还是降低了效率? - 不是,线程越多,效率越慢,但是太少,浪费CPU资源,所以,合理利用CPU
  • 6.并发和并行的区别
  •  并发 --> 在同一个时间段下同时执行多个线程,看起来像同时执行
    
  •  并行 --> 在同一个时间刻度下(不能够在分割的时间单位)执行多个线程,本质就上就是同时执行
    

注解:CPU在某一个最小的时间刻度单位下,执行的是一个进程的一个线程的一个不可再分割的原子性语句
举例: a++ 是线程安全的吗? 不是,声明a和a+1中间有不确定性(另一个进程也在调用a) a>0是安全的
7.同步和异步的区别 – 隐私文件
8.Java虚拟机的启动至少开启了两条线程,主线程和垃圾回收线程

实际操作

Thread简介:
Thread是个普通类
Thread实现了Runnable接口重写了run方法

启动线程的两种方式:

Thread启动线程:
新建class类A继承Thread类,重写run方法:(方法体中可以写方法调用/普通代码)
在测试类的main方法中new A 生成a对象调用start方法,而不是run
Runnable接口启动:
新建类B实现接口Runnable,重写run方法:(方法体中可以写方法调用/普通代码)
在测试类的main方法中th=new Thread(b):将B类的对象b作为参数传入
th调用start方法

案例:要求123功能同时进行:

两种方式实现:
1遍历文件所有
2拷贝文件输出在控制台
3主方法打印1-1000
测试类:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		Searchfile sf = new Searchfile(new File("src"));
		sf.start();
		CopyfileImp cf = new CopyfileImp(new File("a.txt"),new File("acopy2.txt"));
		Thread t=new Thread(cf);
		t.start();
		for(int i=0;i<1000;i++)
			System.out.println(i+"main++++++++++");	
	}

遍历文件夹下所有文件目录

class Searchfile extends Thread{
	File file;
	public Searchfile(File file) {
		super();
		this.file = file;
	}
	public  void sreach(File files){
		if(files==null)
			throw new NullPointerException();
		File[] fs = files.listFiles();
		if(fs.length!=0&&fs!=null)
			for (File f : fs) {
				if(f.isDirectory()){
					sreach(f);
				}else{
					System.out.println(f.getName());
					//if(f.isFile()&&f.getName().endsWith(""))
				}
			}
		System.out.println(files.getName());
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();	
		sreach(file);	
	}	
}

拷贝文件输出在控制台

class CopyfileImp implements Runnable{
	File srcfile;
	File descfile;
	
	public CopyfileImp(File srcfile, File descfile) {
		super();
		this.srcfile = srcfile;
		this.descfile = descfile;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		copy();
	}
	public void copy(){
		try(BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(descfile,true));
				BufferedInputStream bi = new BufferedInputStream(new FileInputStream(srcfile));
				){
			int len=0;
			byte[] bs=new byte[124];
			while((len=bi.read(bs))!=-1){
				bo.write(bs);
				bo.flush();
			}	
			} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}	
	}	
}

实现线程实例化的几种方法:

尤其注意第四种:继承Thread和实现Runnable接口都有时,只会调用Thread中的run方法

		1//匿名子类对象
		new Thread(){};
		
		2//匿名子类对象
		new Thread(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				for(int i=0;i<100;i++)
					System.out.println(i);
			}	
		}.start();
		
		3//匿名对象,参数为接口实现类的匿名对象
		new Thread(new Runnable(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
			for(int i=0;i<100;i++)	
				System.out.println("  +  + "+i);
			}
			
		}).start();;
		
		4//匿名子类对象,参数为接口实现类的匿名对象
		//注意:继承Thread和实现Runnable接口都有时,只会调用Thread中的run方法
		//只打印System.out.println("thread  +  + "+i);
		new Thread(new Runnable(){	
			public void run() {
				// TODO Auto-generated method stub
				for(int i=0;i<100;i++)	
					System.out.println("jiekou  +  + "+i);
				}
			}
			
		){
	public void run() {
				// TODO Auto-generated method stub
				for(int i=0;i<100;i++)	
					System.out.println("thread  +  + "+i);
				
			}
		}.start();;

Lambda表达式开启线程

什么是Lambda表达式 一种函数式接口的新的写法,本质还是匿名内部类,但是这个父类是函数式接口
什么是函数式接口?
只有一个抽象方法的接口称为函数式接口(到时调用的时候就可以不用写方法名称,很方便!)
Runnable, FileFilter

Lambda表达式的语法:

  •  () -> {}
    
  •  () 小括号里面是参数列表,如果一个函数式接口中的抽象方法没有参数,这里可以不写参数
    
  •  -> 固定格式
    
  •  {} 重写函数式接口的抽象方法的方法体
    
  •  如果方法体中只有一条语句,{} 可以省略不写,如果返回值只有一条语句, return关键字要省略
    

接口如下:

@FunctionalInterface
interface ITest {
	void show();
}

@FunctionalInterface
interface IDemo {
	void show(int a, String b);
}

@FunctionalInterface
interface IShow {
	int add(int a, int b);
}

普通类,和三个接口具有关联关系

class Demo {
	
	public void method(ITest test) {
		test.show();	//调用抽象方法
	}
	
	public void method(IDemo d) {
		d.show(10, "sss");	
	}
	
	public void method(IShow s) {
		int add = s.add(100, 200);
		System.out.println(add);
	}
}

具体实现:

public class ThreadDemo05 {
	public static void main(String[] args) {
		
		new Demo().method(()->System.out.println("Lambda表达式的 show"));
		//进method的接口,接口中的方法没有参数:ITest -》void show();
		new Demo().method((a, b)->System.out.println(a + "|" + b));
		//进method的接口,接口中的方法有两个参数,没有返回值: IDemo -》void show(int a, String b);
		new Demo().method((a, b)->a + b);
		//进method的接口,接口中的方法有两个参数,有返回值:IShow -》int add(int a, int b);
		}

引出大头:

//因为这是构造方法实现子类匿名对象,其中参数是Runnable接口的实现类   
刚好他的实现类可以用lambda表达式进行:run方法没有参数所以空()    再{ }写入方法体即可!
new Thread(()->{
	System.out.println("Lambda表达式开启线程");
			for (int i = 0; i < 10000; i++) {
				System.out.println("Lambda:" + i);
			}
		}).start();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值