线程
1.进程和进程的关系与区别,是理解线程概念的前提
进程
应用程序执行的实例
有独立的内存空间和系统资源
线程
CPU调度和分派的基本单位
执行运算的最小单位
2.什么是多线程
如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程”
多个线程交替占用CPU的资源,而非真正的并执行
多线程好处,
充分利用CPU的资源,提高代码性能
简化编程
Thread类
主线程
main()方法即为主线程入口
产生其他子线程 的线程
必须最后完成执行,因为它执行各种关闭动作
线程创建的两种方法
1.继承thread类
编写简单,可直接操作线程
(1)创建MyThread类继承Thread类 ,并重写run()方法
package thread_21;
//创建并启动线程
public class MyThread extends Thread{
public void run() {
for(int i=1;i<=100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
(2)编写测试类TestThread
package thread_21;
//测试类
public class TestThread {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建线程对象
MyThread myThread=new MyThread();
MyThread myThread2=new MyThread();
//启动线程
//抢占CPU
// myThread.start();
// myThread2.start();
//是否可以调用run()方法启动线程?
//(1)只有主线程一个执行路径(2)一次调用两次run()方法
//run()方法被当作main()中的一个普通方法执行,失去了线程的意义
myThread.run();
myThread2.run();
}
}
2.实现Runnable创建线程
(1)定义MyRunnable类实现Runable接口
package thread_21;
//创建线程 :实现Runnable接口
public class Mthread2 implements Runnable{
}
(2)实现run()方法,编写
package thread_21;
//创建线程 :实现Runnable接口
public class Mthread2 implements Runnable{
public void run() {
for(int i=1;i<=100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
(3)创建线程对象 ,调用start()方法启动线程
package thread_21;
//测试线程
public class TestThread2 {
public static void main(String[] args) {
//创建线程对象
Runnable runnable=new Mthread2();
Thread thread=new Thread(runnable);
Thread thread2=new Thread(runnable);
//启动线程
thread.start();
thread2.start();
}
}
调用run()和start()方法创建线程的区别:
使用start()方法主线程和子线程并行交替执行
使用run()方法,只有主线程一条执行
线程的状态
自定义线程类MyThread ,继承Runnable类,重写run()方法,定义5s后线程休眠
package threadstate_22;
public class MyThread implements Runnable{
@Override
public void run() {
System.out.println("线程正在运行!!");
//线程休眠5秒
try {
System.out.println("线程休眠开始,正在阻塞状态");
Thread.sleep(5000);
System.out.println("线程休眠结束,正在阻塞状态");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
测试类TestThread
package threadstate_22;
//测试线程的集中状态
public class TestThread {
public static void main(String[] args) {
// TODO Auto-generated method stub
Runnable runnable = new MyThread();
Thread t = new Thread(runnable);
System.out.println("线程处于创建状态");
t.start();
System.out.println("线程处于就绪状态");
}
}
线程调度
1.集中线程调度的方法(作用)
2.如何设置线程优先级
//线程调度
thread2.setPriority(10);
thread.setPriority(1);
thread.setPriority(Thread.MAX_PRIORITY);
thread2.setPriority(Thread.MIN_PRIORITY);
3.掌握如何实现线程休眠
//s:线程休眠的秒数
public static void bySec(long s){
for(int i=1;i<=s;i++){
System.out.println(i+"秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4.join()抢占线程
自定义MyThread类实现Runnable接口,重写run()方法,循环输出30个线程名
package threaddispatch;
public class MyThread implements Runnable{
public void run() {
for(int i=1;i<30;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
测试类
package threaddispatch;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建子线程对象t
Runnable runnable=new MyThread();
Thread t=new Thread(runnable, "myThread");
t.start();
//主线程main做的事情
for(int i=1;i<=20;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
//当i=5的时候,强制把t线程加入执行
//线程调度:join()
//--等待线程终止 ,等待t线程终止:等待t线程执行结束后,main主线程再继续执行
if(i==5){
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
5.使用yield()暂停正在执行的线程对象,并执行其他线程
首先掌握两点:
(1)这是线程的静态方法,不需要创建对象,而通过类名.yield()去使用
(2)从某种意义上,join和yield作用相反
使用yield()暂停正在执行的线程对象,并执行其他线程
被暂停的线程对象处于就绪状态,不转为阻塞状态
public static void yield()
多线程共享数据
可能带来的问题:数据不安全
原因:多线程共同操作数据时,引发的冲突(如延迟时,操作为全部完成等等)
思考:如何解决?
线程同步
实现线程同步的两种方式
(1)第一种
使用synchronized修饰的方法控制对类成员变量的访问
访问修饰词 synchronized 返回类型 方法名 (参数列表){......}
或者
synchronized 访问修饰词 返回类型 方法名 (参数列表){......}
synchronized 就是为当前的线程声明一把锁
(2)第二种
使用synchronized关键词修饰的代码块
synchronized(syncObject){
//需要同步的代码
}