黑马程序员---java基础------------------多线程
线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。
线程的创建
一:继承Thread类。步骤:
1,定义类继承Thread。
2,复写Thread类中的run方法。 目的:将自定义代码存储在run方法。让线程运行。
class Demo extends Thread
{
public void run()
{
for(int x=0; x<60; x++)
System.out.println("demo run----"+x);
}
}
3,调用线程的start方法, 该方法两个作用:启动线程,调用run方法。
class ThreadDemo {
public static void main(String[] args) {
//for(int x=0; x<4000; x++)
//System.out.println("Hello World!");
Demo d = new Demo();//创建好一个线程。
//d.start();//开启线程并执行该线程的run方法。
d.run();//仅仅是对象调用方法。而线程创建了,并没有运行。
for(int x=0; x<60; x++)
System.out.println("Hello World!--"+x);
}
}
线程的运行状态:
二:创建线程的第二种方式:实现Runable接口
步骤:
1,定义类实现Runnable接口
2,覆盖Runnable接口中的run方法。 将线程要运行的代码存放在该run方法中。
3,通过Thread类建立线程对象。
4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
class Ticket implements Runnable//extends Thread {
private int tick = 100;
public void run() {
while(true) {
if(tick>0)
System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
}
}
}
class TicketDemo {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread t1 = new Thread(t);//创建了一个线程;
Thread t2 = new Thread(t);//创建了一个线程;
Thread t3 = new Thread(t);//创建了一个线程;
Thread t4 = new Thread(t);//创建了一个线程;
t1.start();
t2.start();
t3.start();
t4.start();
}
}
为什么要将Runnable接口的子类对象传递给Thread的构造函数?
因为,自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。
实现方式和继承方式有什么区别呢?
实现方式好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存在接口的子类的run方法。
获取当前线程对象:static Thread currentThread();
获取线程名称:getName();
class Test extends Thread {
Test(String name) { //父类有这样的构造方法
super(name);
}
public void run() {
for(int x=0; x<60; x++) {
System.out.println((Thread.currentThread()==this)+"..."+this.getName()+" run..."+x);
}
}
}
class ThreadTest
{
public static void main(String[] args)
{
Test t1 = new Test("one---");
Test t2 = new Test("two+++");
t1.start();
t2.start();
}
}
多线程的安全问题:通过分析,发现,打印出0,-1,-2等错票。问题的原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执
行完,另一个线程参与进来执行。导致共享数据的错误。解决办法:对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。这就出来了
同步代码块
synchronized(对象) {
需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。 没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
同步的前提:1,必须要有两个或者两个以上的线程;2,必须是多个线程使用同一个锁。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源。
class Ticket implements Runnable {
private int tick = 1000;
Object obj = new Object();
public void run() {
while(true) {
synchronized(obj) {
if(tick>0) {
//try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
}
}
}
}
}
class TicketDemo2 {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
同步函数:同步代码块用来封装代码的,函数也是来封装代码的,我们试图让函数具备同步性,也可以达到相同的效果。
class Bank {
private int sum;
public synchronized void add(int n) {
sum = sum + n;
try{Thread.sleep(10);
}catch(Exception e){}
System.out.println("sum="+sum);
}
}
class Cus implements Runnable {
private Bank b = new Bank();
public void run() {
for(int x=0; x<3; x++) {
b.add(100);
}
}
}
class BankDemo {
public static void main(String[] args) {
Cus c = new Cus();
Thread t1 = new Thread(c);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}
验证同步函数的锁对象是this:如果直接将synchronized关键字放到run() 函数上做成同步函数,发现效果不行 ,应为只启动了0号线程,分析后得知,是同步的代码没弄清楚,后来将同步代码部分提取后,封装成独立的show()函数调用并同步synchronized,就可以了。这个时候问一个问题,它的锁是什么呢?函数需要被对象调用,函数都有一个所属对象的引用时this所以同步函数的锁对象是this。为了验证,使用两个线程买票,一个线程在同步代码快中,一个在同步函数中,都在执行买票动作,如果要是同步就不会出现错误的票。
class Ticket implements Runnable {
private int tick = 100;
//Object obj = new Object();
boolean flag = true;
public void run() {
if(flag) {
while(true) {
//synchronized(this) {
if(tick>0) {
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);
}
}
}
}
else
while(true)
show();
}
public synchronized void show()//this
{
if(tick>0) {
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);
}
}
}
class ThisLockDemo {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try{
Thread.sleep(10);
}catch(Exception e){}
t.flag = false;
t2.start();
}
}
函数被静态修饰后,使用的锁是:类名.class
class Ticket implements Runnable {
private static int tick = 100;
//Object obj = new Object();
boolean flag = true;
public void run() {
if(flag) {
while(true) {
synchronized(Ticket.class) {
if(tick>0) {
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);
}
}
}
}
else
while(true)
show();
}
public static synchronized void show() {
if(tick>0) {
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);
}
}
}
class StaticMethodDemo {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(Exception e){}
t.flag = false;
t2.start();
}
}
单例设计模式
懒汉式:
class Single {
private static Single s = null;
private Single(){}
public static Single getInstance() {
if(s==null) {
synchronized(Single.class) {
if(s==null)
//--->A;
s = new Single();
}
}
return s;
}
}
class SingleDemo {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
死锁:
class Test implements Runnable {
private boolean flag;
Test(boolean flag) {
this.flag = flag;
}
public void run() {
if(flag) {
while(true) {
synchronized(MyLock.locka) {
System.out.println(Thread.currentThread().getName()+"...if locka ");
synchronized(MyLock.lockb) {
System.out.println(Thread.currentThread().getName()+"..if lockb");
}
}
}
}
else {
while(true) {
synchronized(MyLock.lockb) {
System.out.println(Thread.currentThread().getName()+"..else lockb");
synchronized(MyLock.locka) {
System.out.println(Thread.currentThread().getName()+".....else locka");
}
}
}
}
}
}
class MyLock {
static Object locka = new Object();
static Object lockb = new Object();
}
class DeadLockTest {
public static void main(String[] args) {
Thread t1 = new Thread(new Test(true));
Thread t2 = new Thread(new Test(false));
t1.start();
t2.start();
}
}
转载于:https://www.cnblogs.com/zhaolibin198627/archive/2013/05/24/3097980.html
黑马程序员---java基础------------------多线程相关推荐
- 黑马程序员——java基础---多线程(二)
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 线程间的通信:简单来说,就是多个线程在操作同一资源,但操作的动作不同. 试想一下,对于同一个资 ...
- 黑马程序员——Java基础---多线程
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 多线程 一.概述 说起多线程,我们就需要首先来谈谈什么叫做进程.所谓进程,就是在计算机上正在进行 ...
- 黑马程序员JAVA基础-多线程
------- android培训.java培训.期待与您交流! ---------- 线程: 线程是进程中的一个独立的控制单元 线程在控制着进程的执行 一个进程中至少有一个线程 线程的创建 第一种方 ...
- 黑马 程序员——Java基础---流程控制
黑马程序员--Java基础---流程控制 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------ 一.概述 Java提供了两种基本的流程控制结构:分支结构 ...
- 黑马 程序员——Java基础---IO(下)
黑马程序员--Java基础---IO(下) ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------ 一.概述 Java除了基本的字节流.字符流之外,还提供 ...
- 黑马程序员-Java基础:面向对象(上)
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.面向对象概述 当需求单一,或者简单时,我们一步一步去操作没问题,并且效率也挺高.可随着需求的 ...
- 黑马程序员——java的多线程
------- android培训.java培训.期待与您交流! ---------- 前言:通过观看毕向东老师的java基础视频,查漏补缺,将一些自己掌握的还不牢固的知识写出来,希望和大家交流分享. ...
- 黑马程序员--Java基础加强篇
开发工具使用 --------------------------------------------------------------------------------------------- ...
- 黑马程序员-Java基础:设计模式总结
--Java培训.Android培训.iOS培训..Net培训.期待与您交流! -- Java基础部分设计模式 一.设计模式概述 设计模式(Design pattern)是一套被反复使用.多数人知晓的 ...
最新文章
- 效率提升看得见 神策 A/B 测试可视化试验能力正式上线
- 奇怪的吃播_吃播,我看吐了!
- Expression Blend实例中文教程(4) - 布局控件快速入门Canvas
- warning no newline at the end of file
- 项目一计算机基础知识考核题,2013计算机基础知识试题及答案
- thinkpad t460p恢复原厂系统以及设置的方式
- git 修改远程仓库地址
- R中读取文件,找不到路径问题 No such file or directory
- 最新PHP乐购社区源码+点卡购物系统
- radius服务器搭建
- QPainter画箭头
- 【Linux系统】第2节 虚拟机中安装Kali系统
- 显著性水平和p值的理解
- Android:手机号码归属地查询
- 牛腩新闻发布--触发器语句
- .com与.top域名有什么区别
- Android 科大讯飞语音评测SDK 踩坑实录
- python有趣小程序春节祝福-用python实现新年祝福微信的自动回复
- 在Keras的Embedding层中使用预训练的word2vec词向量
- 金蝶kis记账王怎么反审核凭证