进程:应用程序的的执行实例,有独立的内存空间和系统资源
线程:CPU调度和分派的基本单位,应用程序的的执行实例
多线程:
如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程”多个线程交替占用CPU资源,而非真正的并行执行
多线程好处:
充分利用CPU的资源
简化编程模型
带来良好的用户体验
主线程
main()方法即为主线程入口
产生其他子线程的线程
必须最后完成执行,因为它执行各种关闭动作
Thread类
Java提供了java.lang.Thread类支持多线程编程
下面程序显示主线程名
public static void main(String args[]) {
Thread t= Thread.currentThread();
System.out.println("当前线程是: "+t.getName());
t.setName("MyJavaThread");
System.out.println("当前线程名是: "+t.getName()); }
在Java中创建线程的三种方式:
1、继承Thread类,重写run()方法:便于代码复用
定义MyThread类继承Thread类
重写run()方法,编写线程执行体
创建线程对象,调用start()方法启动线程
public class TestThread extends Thread { public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+ ",第"+(i+1)+"次运行"); } } public TestThread(String name) { super(name); } public static void main(String[] args) { TestThread t1=new TestThread("线程1"); TestThread t2=new TestThread("线程2"); t1.start(); t2.start(); } }
2、实现Runnable接口,重写run()方法:用处广泛,便于扩展
定义MyRunnable类实现Runnable接口
实现run()方法,编写线程执行体
创建线程对象,调用start()方法启动线程
public class TestRunnable implements Runnable { public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+ ",第"+(i+1)+"次运行"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { TestRunnable tr=new TestRunnable(); TestRunnable tr2=new TestRunnable(); Thread t1=new Thread(tr,"线程A"); Thread t2=new Thread(tr2,"线程B"); t1.start(); t2.start(); } }
3、实现Callable接口,重写call()方法:特定场景需要返回值时使用;call()方法可以引发异常
可以通过为FutureTask的构造方法,提供Callable来创建FutureTask对象。然后将FutureTask对象提供给Thread的构造函数以创建Thread对象
public class TestCall implements Callable<Integer> { static int i=0; public Integer call() throws Exception{ for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName()+ ",第"+(i+1)+"次运行"); } return ++i; } public static void main(String[] args) throws ExecutionException,InterruptedException { TestCall c=new TestCall(); FutureTask ft=new FutureTask(c); //提供Callable来创建FutureTask对象,存储从call()获得的结果 FutureTask ft2=new FutureTask(c); Thread t1=new Thread(ft);//将FutureTask对象提供给Thread的构造函数以创建Thread对象 Thread t2=new Thread(ft2); t1.start(); t2.start(); System.out.println(ft.get()); System.out.println(ft2.get()); } }
线程的状态:
创建、就绪、运行、阻塞、死亡
线程的调度:
多线程共享数据 可能带来的问题数据不安全
原因: 多线程共同操作数据时, 引发的冲突( 如延迟时, 操作未全
部完成等等)
解决方法:线程同步( 同步方法、同步代码块( synchronized ))
线程同步·:即各线程之间要有个先来后到, 不能一窝蜂
线程同步其实是' 排队" : 上锁, 排队, 一个一个来, 不能同时操做
多个并发线程访问同一资源的同步代码块时
同一时刻只能有一个线程进入synchronized ( this ) 同步代码块
当|一个线程访问一个synchronized ( this ) 同步代码块时, 其他
synchronized ( this ) 同步代码块同样被锁定
当一个线程访问一个synchronized ( this ) 同步代码块时, 其他线
程可以访问该资源的非synchronized ( this ) 同步代码
常见的线程安全的类型:.(右边线程安全,左边非线程安全)
ArrayLHist-->Vector
HashMap-->HashTable(旧)
-- >ConcurrentHashMap
StringBuilder--> StringBuffer