进程是一个应用程序(一个进程一个软件)
线程是一个进程中的执行场景/执行单元
一个进程可以启动多个线程
2.对于java来说,启动JVM,JVM在启动一个主线程调用main方法,同时再启动一个垃圾回收器线程负责看护,回收垃圾。
进程与进程之间内存独立不共享。
线程与线程之间在java语言中:
堆内存和方法去内存共享。
栈内存独立,一个线程一个栈。
4.多线程机制可以提高程序处理效率。
5.使用对线程机制之后,main方法结束,程序可能不会结束。main方法结束,只是主栈空了,其他栈(线程)可能还在压栈弹栈。
方法区、堆内存只有一个。多线程共享 。
一个栈一个线程。支栈:分支线程。
7.什么是多线程并发?
t1线程执行t1的,t2线程执行t2的。
t1不会影响t2,t2不会影响t1。这才叫多线程并发。
8.对于一个单核的CPU来说,真的可以做到多线程并发吗?
对于多核的CPU电脑,真正的多线程并发是没有问题的。
单核的CPU表示只有一个大脑:
不能够做到真正的多线程并发,但是可以给人一种”多线程并发“的感觉。对于单核的CPU来说,在某一个时间点上实际上只能处理一件事情,但是由于CPU运行速度处理极快,多个线程之间频繁切换执行,给人的感觉就是同时在做。
java支持多线程机制,并且java已经将多线程实现了,我们只需要继承就行。
怎么创建线程对象? new就行了
怎么启动线程? 调用线程对象的start()方法。
public class Test{ public static void main(String[] args) { //主线程在主栈中 //创建分支线程对象 MyThread th = new MyThread(); //启动线程 th.start(); //start()方法的作用:启动一个分支线程,在JVM中开辟一个新的栈空间, //这段代码任务完成之后,瞬间就结束了。 //这段代码的任务只是为了开启一个新的栈空间,只要新的栈空间开出来, //start()方法就结束了。线程就启动成功了。 //启动成功的线程会自动调用run()方法并且run()方法在分支线的栈底部(压栈)。 //run方法在分支线程的底部,main方法在主栈的栈底部,run和main是平级的。 //直接调用run方法,与调用start的方法有啥区别? //th.run();//不会启动线程,不会分配新的分支栈。(等于在同一个栈中,单线程) //这里的代码还是运行在主线程中 for(int i = 0; i < 100;i++) { System.out.println("main"); } } }
以上代码输出结果有这样的特点:有先有后。有多有少。Why?
某个线程抢到执行权。
推荐接口:面向接口编程。一个类实现了接口,它还可以去继承其它的类,更灵活。
class MyRunable implements Runnable{ @Override public void run() { for(int i = 0; i < 100;i++) { System.out.println("MyRunabale"); } } } public class Test{ public static void main(String[] args) { //创建一个可运行的对象 MyRunable r = new MyRunable(); //将可运行的对象封装成一个线程对象 Thread t = new Thread(r); //合并代码 //Thread tt = new Thread(new MyRunable()); //启动线程 t.start(); for(int i = 0; i < 100;i++) { System.out.println("main"); } } }
public class Test{ public static void main(String[] args) { Thread t = new Thread(new Runnable() { @Override public void run() { for(int i = 0; i < 100;i++) { System.out.println("Runabale"); } } }); //启动线程 t.start(); for(int i = 0; i < 100;i++) { System.out.println("mian"); } } }
新建状态、就绪状态、运行状态、运行状态、阻塞状态、死亡状态
11.1、怎么获取线程对象?
public static native Thread currentThread()
Thread t = Thread.currentThread();//返回t就是当前线程。
11.2、线程对象的名字:线程对象 .getName()
11.3、修改线程对象名字:线程对象 .setName("")
11.4、当线程没有设置名字:Thread-0、Thread-1
public class Test{ public static void main(String[] args) { MyRun h = new MyRun(); h.doSome(); System.out.println(); //这个代码出现在main中,所以线程就是主线程。 Thread tt = Thread.currentThread(); System.out.println(tt.getName());//main MyRun t = new MyRun(); //t.setName("t1"); String tName = t.getName(); //默认Thread-0 System.out.println(tName); MyRun t2 = new MyRun(); String tName2 = t2.getName(); //Thread-1 System.out.println(tName2); System.out.println(); t.start(); t2.start(); } }
11.5、关于线程sleep()方法:
public static native void sleep(long millis) throws InterruptedException
public class Test{ public static void main(String[] args) { try { Thread.sleep(1000*5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("HelloWorld"); for(int i = 0;i<10;i++){ System.out.println(Thread.currentThread().getName() + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
11.6、终止线程的睡眠(不是终断线程的执行)
中断睡眠的方式依靠了java的异常处理机制java.lang.InterruptedException: sleep interrupted
class MyRun1 implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+ "--> begin"); try { //子类重写父类不能抛出比父类更多、更宽的异常 Thread.sleep(1000*60*60); } catch (InterruptedException e) { //打印异常信息 e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+ "--> end"); } } public class Test{ public static void main(String[] args) { Thread t = new Thread(new MyRun1()); t.setName("t"); t.start(); //希望在5秒后,t线程醒来 try { Thread.sleep(1000*5); } catch (InterruptedException e) { e.printStackTrace(); } //终断t线程的睡眠 t.interrupt(); } }
12.1、什么时候数据在多线程并发的环境下会存在安全问题呢?
满足以上三个条件之后,就会存在线程安全问题。
12.2、怎么解决线程安全问题?
线程同步机制:线程排队执行。(不能并发)
会牺牲一部分效率。(安全第一)
12.3、synchronized的三种方法:
第一种:同步代码块
synchronized(线程共享对象){
同步代码块;
}
第二种:在实例方法上使用synchronized
表示共享对象一定是this
并且同步代码块是整个方法体。
第三种:在静态方法上使用synchronized
表示找类锁。
类锁永远只有1把。
JavaSE更新基本结束,后续或许会补充,或许不会。
上一篇:十三、IO流
下一篇:数据结构:持续更新中
原文:https://www.cnblogs.com/arick/p/13779577.html