创建线程类
java.lang.Thread类代表线程,所有的线程对象必须是Thread类的子类实现,每个线程的作用是完成一定的任务,实际上就是执行一段程序流程,使用线程执行来代表这段程序
|
实现步骤
- 创建一个Thread类的子类
- 在Thread的子类中重写Thread的run方法(开启线程需要做什么写在run方法中)
- 在测试类里面创建Thread的子类对象
- 调用Thread类中的start方法(开启线程的方法),会自动执行run方法
注意:
1.多个线程同时运行哈,CPU选择线程就是随机单个选择并使用
2.多次启动一个线程是不可以的,特别是当线程结束不能再次调用
3.Java中属于抢占式的执行
||||||||||||||||||||||
||||||||||||||||||||||
||||||||||||||||||||||
多线程的原理:
原理:提高CPU的使用效率,但是程序运行速率不会提升
必须是Thread或者Thread的子类调用start方法才能开启线程
|
程序运行main方法的时候JVM启动一个进程,主进程main在main调用的时候创建,随着Thread对象调用start方法,另一个新的线程也启动了。如此下来,每个线程创建自己的内存空间进行方法的压栈和弹栈,当线程任务结束,线程就会被释放掉,进程也就结束了。
|
Thread类
构造方法: - public Thread();分配一个新的线程对象
- public Thread(String name);分配一个新的线程对象,并给线程命名
- public Thread(Runable taegrt);分配一个指定目标的新的线程对象
- public Thread(Runable taegr,String name);分配一个指定目标的新的线程对象,并给线程命名
|
方法 - public String getName();获取当前线程名称
- public void start();线程开始执行,JVM执行线程的run方法
- public void run();线程要执行的任务在此方法中定义
- public static void sleep(long mills);使得当前执行的线程以指定毫秒数停止
- public static Thread currentThread();获取当前执行线程对象的引用
|||||||||||||||||||||||||||
|||||||||||||||||||||||||||
|||||||||||||||||||||||||||
创建线程的两种方式
1.继承Thread类
2.实现Runable接口
步骤: - 定义Runable接口实现类。实现接口
- 重写该接口的run方法,该run方法的方法体同样是该线程的线程执行体
- 测试类里面,创建Runable接口实现类的实例
- 以此实例对象作为Thread类的targer来创建Thread对象才是真的线程对象
- 调用Thread类中的state方法自行开启run方法
Runable优点
1.避免单继承
一个类只能直接继承一个父类,父类继承了Thread类就不能继承其他类,实现Runable接口之后还能继承其他类
2.增前来扩展性,降低了程序的耦合性(解耦合)
- 实现Runable接口方式,吧设置线程和启用线程进行分离效果
- 实现类中重写run方法,设置线程任务
- 调用类里面调用start方法调用线程
|||||||||||||||||||||
|||||||||||||||||||||
|||||||||||||||||||||
Thread类和Runable接口的区别
如果一个类继承了Thread类,不适合资源共享,但是实现Runable接口的话就很容易实现资源共享,实现Runable接口比继承Thread更有优势:
- 适合多个相同程序代码去共享一个资源
2.可以避免java中继承的局限性
3.增加了程序的扩展性,实现类解耦操作,胆码可以被共享,可以实现代码独立
4.线程池,只能放入实现Runable接口或者Callable的接口线程中,不能直接放入继承Thread类中
||||||||||||||||||||||
||||||||||||||||||||||
||||||||||||||||||||||
匿名内部类改造线程
//我们用现成借口Runable,使用匿名内部类
new Thread( new Runnable() {
@Override
public void run() {
for (int i = 20; i <40; i++) {
System.out.println(i);
}
}
}).start();
||||||||||||||||||||
||||||||||||||||||||
||||||||||||||||||||
线程安全
线程安全问题都是由全局变量或者静态引起的,若每个线程对全局变量,静态变量只有读操作,没有写操作,一般来说这个全局变量是线程安全的,,,多个线程同时操作,一般需要线程同步,否则就容易造成线程安全问题。多半来说就是多个线程同时对程序进行写操作而造成的线程不安全。
|||||||||||||||||||||
|||||||||||||||||||||
|||||||||||||||||||||
线程同步
窗口以进入操作的时候窗口而和窗口三在外等,当窗口已线程结束,窗口二或者窗口三才能进入售卖,也就是说摸个线程修改资源的时候,其他的线程不能修改,只有等上一个线程修改完毕后后面的才会修改保证数据同步,解决线程不安全
|||||||||||||||||||||||
|||||||||||||||||||||||
|||||||||||||||||||||||
实现线程同步三种方法
1.同步代码块
synchronized关键字可以用于方法中某个代码块中,表示只对这个代码块的资源实行互斥访问,
同步锁:是一个对象,是一个抽象概念,
【锁对象可以是任意类型,包括Object】
【多个线程对象要使用同一把锁】
注意:只有一个线程能进入同步锁,谁抢到了这个锁,谁就进行资源修改操作
同步内得线程,会占用锁,线程结束之后才会释放锁,然后那同步外的线程才有机会取获取锁,得到多之后才能进入同步,因为需要不停的判断锁是否存在,所以效率很低,消耗资源很大
格式:
synchronized(同步锁){
//需要他不操作的代码
}