①多任务—用户可以在同一时间内运行多个应用程序,每个应用程序被称作一个任务
②多线程—多个线程并发执行
③程序、进程、线程
程序—指令和数据的有序集合,是静态的概念
进程—执行程序的一次执行过程,是动态的概念,系统资源分配的单位
线程—独立执行的路径,是CPU调度和执行的单位,一个进程至少有一个线程
①三种创建方式
1.继承Thread类
2.实现Runnable接口
3.实现Callable接口
②通过Thread类创建
1.自定义线程类继承Thread类
2.重写run()方法,编写线程执行体
3.创建线程对象,调用start()方法启动线程
1 public class TestThread1 extends Thread{
2 @Override
3 public void run() {
4 //run()方法线程体
5 for(int i=0;i<20;i++){
6 System.out.println("我正在编程------"+i);
7 }
8 }
9 ?
10 public static void main(String[] args) {
11 //main线程,主线程
12 //线程开启不一定立即执行,由CPU调度安排
13 TestThread1 testThread1=new TestThread1();
14 //testThread1.run();//在主线程中顺序执行
15 testThread1.start();//在主线程中交替执行
16 ?
17 for(int i=0;i<2000;i++){
18 System.out.println("我正在学习多线程------"+i);
19 }
20 }
21 }
③通过Runnable接口创建
1.定义一个类实现Runnable接口
2.重写run()方法,编写线程执行体
3.创建线程对象,调用start()方法启动线程
好处是避免了单继承局限性,灵活方便,方便同一个对象被多个线程使用
1 public class TestThread3 implements Runnable{
2 @Override
3 public void run() {
4 //run()方法线程体
5 for(int i=0;i<20;i++){
6 System.out.println("我正在编程------"+i);
7 }
8 }
9 ?
10 public static void main(String[] args) {
11 //创建Runnable接口的实现类对象
12 TestThread3 testThread3=new TestThread3();
13 ?
14 //创建线程对象,通过线程对象来开启线程
15 new Thread(testThread3).start();
16 ?
17 for(int i=0;i<2000;i++){
18 System.out.println("我正在学习多线程------"+i);
19 }
20 }
21 }
④实现Callable接口
1.实现Callable接口,需要返回值类型
2.重写call方法,需要抛出异常
3.创建目标对象
4.创建执行服务器:ExecutorService ser=Executors.newFixedThreadPool(1);
5.提交执行:Future<Boolean> result1=ser.submit(t1);
6.获取结果:boolean r1=result1.get();
7.关闭服务:ser.shutdownNow();
1 public class TestCallable implements Callable<Boolean> {
2 private String url;
3 private String name;
4 ?
5 public TestCallable(String url,String name){
6 this.url=url;
7 this.name=name;
8 }
9 ?
10 @Override
11 public Boolean call() throws Exception {
12 WebDownloader1 webDownloader=new WebDownloader1();
13 webDownloader.downloader(url,name);
14 System.out.println("下载文件名为"+name);
15 return true;
16 }
17 ?
18 public static void main(String[] args) throws ExecutionException, InterruptedException {
19 TestCallable t1=new TestCallable("http://commons.apache.org/proper/commons-io/images/commons-logo.png","6.jpg");
20 ?
21 //创建执行服务
22 ExecutorService ser= Executors.newFixedThreadPool(1);//创建线程池,需要1个线程
23 ?
24 //提交执行
25 Future<Boolean> r1=ser.submit(t1);
26 ?
27 //获取结果
28 boolean rs1=r1.get();
29 ?
30 //关闭服务
31 ser.shutdownNow();
32 }
33 }
34 ?
35 //下载器
36 class WebDownloader1{
37 //下载方法
38 public void downloader(String url,String name){
39 try {
40 FileUtils.copyURLToFile(new URL(url),new File(name));
41 } catch (IOException e) {
42 System.out.println("IO异常,downloader出现了问题");
43 }
44 }
45 }
①真实对象和代理对象都要实现同一个接口
②代理对象要代理真实角色
③好处
1.代理对象可以做很多真实对象做不了的事情
2.真实对象专注做自己的事情
1 public class StaticProxy {
2 public static void main(String[] args) {
3 You you=new You();
4 marryCompany marry=new marryCompany(you);
5 marry.getMarry();
6 }
7 }
8 ?
9 interface Marry{
10 void getMarry();
11 }
12 ?
13 ?
14 class You implements Marry{
15 @Override
16 public void getMarry() {
17 System.out.println("You------>Marry");
18 }
19 }
20 ?
21 class marryCompany implements Marry{
22 private You you;
23 public marryCompany(You you){
24 this.you=you;
25 }
26 @Override
27 public void getMarry() {
28 befor();
29 you.getMarry();
30 after();
31 }
32 public void befor(){
33 System.out.println("结婚前,要布置现场");
34 }
35 public void after(){
36 System.out.println("结婚后,收尾款");
37 }
38 }
①避免了匿名内部类定义过多;让代码看起来更简洁;去掉了一堆没有意义的代码,只留下核心逻辑
②函数式接口(Functional Interface)—只包含唯一一个抽象方法
对于函数式接口可以通过Lamda表达式来创建该接口的对象
1 public class TestLamda {
2 public static void main(String[] args) {
3 //Lamda简化
4 ILove love=(int a)->{
5 System.out.println("I Love------>"+a);
6 };
7 love.lamda(3);
8 ?
9 //1.简化参数 多个参数也可以去掉参数,但要都去掉
10 ILove love1=(a)->{
11 System.out.println("I Love------>"+a);
12 };
13 love1.lamda(6);
14 ?
15 //2.简化括号 多个参数时括号不可以去掉
16 ILove love3=a->{
17 System.out.println("I Love------>"+a);
18 };
19 love3.lamda(9);
20 ?
21 //3.简化花括号 只有在方法中只有一行语句时可以去掉花括号
22 ILove love4=a->System.out.println("I Love------>"+a);
23 love4.lamda(12);
24 }
25 }
26 ?
27 interface ILove{
28 void lamda(int a);
29 }
①线程状态间转换
②线程停止
1.建议线程正常停止—利用次数,不建议死循环
2.建议使用标志位—设置一个标志位
3.不要使用stop或者destroy等过时或者JDK不建议使用的方法
1 public class ThreadStop extends Thread{
2 ?
3 private boolean flag=true;
4 ?
5 @Override
6 public void run() {
7 int i=0;
8 while(flag){
9 System.out.println("run Thread------"+i++);
10 }
11 }
12 ?
13 public void Stop(){
14 this.flag=false;
15 }
16 ?
17 public static void main(String[] args) {
18 ThreadStop t=new ThreadStop();
19 new Thread(t).start();
20 for(int i=0;i<1000;i++){
21 if(i==900){
22 t.Stop();
23 System.out.println("线程该停止了");
24 }
25 System.out.println("main"+i);
26 }
27 }
28 }
②线程休眠
1.sleep(时间)指定当前线程阻塞的毫秒数
2.sleep存在异常InterruptedException
3.sleep时间到达后线程进入就绪状态
4.sleep可以模拟网络延迟,倒计时等
5.sleep每一个对象都有一个锁,sleep不会释放锁
③线程礼让
1.让当前正在执行的线程暂停,但不阻塞;Thread.yield()
2.将线程从运行状态转为就绪状态
3.礼让不一定成功
④线程合并
Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
1 public class TestJoin implements Runnable{
2 @Override
3 public void run() {
4 for(int i=0;i<1000;i++){
5 System.out.println("线程vip来了"+i);
6 }
7 }
8 ?
9 public static void main(String[] args) throws InterruptedException {
10 TestJoin t=new TestJoin();
11 Thread thread=new Thread(t);
12 thread.start();
13 ?
14 //主线程
15 for(int i=0;i<500;i++){
16 if(i==200){
17 thread.join();//插队
18 }
19 System.out.println("主线程"+i);
20 }
21 }
22 }
通过Thread类的对象thread调用getState()方法
1 public class TestState {
2 public static void main(String[] args) throws InterruptedException {
3 Thread thread=new Thread(()->{ //重写run()方法
4 for(int i=0;i<5;i++){
5 try {
6 Thread.sleep(1000);
7 } catch (InterruptedException e) {
8 e.printStackTrace();
9 }
10 }
11 System.out.println("执行结束了!");
12 });
13 ?
14 //观察状态
15 Thread.State state=thread.getState();
16 System.out.println(state);//NEW
17 ?
18 //观察启动后
19 thread.start();
20 state=thread.getState();
21 System.out.println(state);//RUN
22 ?
23 while(state!=Thread.State.TERMINATED){ //只要线程不终止,就一直输出状态
24 Thread.sleep(100);
25 state=thread.getState();
26 System.out.println(state);//TIMED_WAITING
27 }
28 }
29 }
①线程调度器按照优先级决定应该调度哪个线程来执行
②线程的优先级用数字表示,范围从1~10
Thread.MIN_PRIORITY=1;
Thread.MAX_PRIORITY=10;
Thread.NORM_PRIORITY=5;
③通过getPriority()方法获取优先级;通过setPriority()方法改变优先级
④先设置优先级,再启动线程
⑤优先级低只意味着获得调度的概率低,并不是优先级低就不会被调用了,要看CPU的调度
①线程分为用户线程和守护线程(daemon)
②虚拟机必须确保用户线程执行完毕,虚拟机不必等待守护线程执行完毕,如后台记录操作日志、监控内存、垃圾回收等
God god=new God();
Thread thread=new Thread(god);
thread.setDaemon(true);//默认是false,是用户线程
原文:https://www.cnblogs.com/yqsumAll/p/14399270.html