线程:

方式一:继承Thread类并且复写run方法.

格式:

class MyThread extends Thread

{

  public void run()

  {

    线程中要运行的代码.

  }

}

其步骤为:

1.定义类继承Thread类.

2.复习run方法.---->目的是:用于存储线程中要运行的代码,将自定义的代码存储在run方法中,让线程运行.

3.调用线程的start方法

  注意:不是调用run方法.

线程的名字:一般线程有默认的名字,形式为:Thread-编号,编号是从0开始标记的.

也可以获取当前运行线程的名字,用方法:Thread.currentThread().getName()

Thread.currentThread() 是用于获取当前线程的对象.(静态的).

自定义设置线程的名字可以用setName()或者构造函数来设置.

有关线程的继承方式的代码实例和练习:

 /*
线程:步骤:
1.定义一个类继承Thread
2.复写类中的润方法
3.创建一个对象(创建一个对象也就创建了一个线程)
4.调用线程的start()方法,调用start方法后,启动了线程,同时也调用了run()方法.
*/
class MyThread extends Thread //第一步
{
public void run() //第二步
{
for(int x = 0; x < 60; x++)
System.out.println("MyThread run!====="+x);
}
} class ThreadDemo
{
public static void main(String args[])
{
MyThread mt = new MyThread();//创建了一个线程. //第三步
mt.start(); // 开启线程并运行该线程的run方法. //第四步
//mt.run(); // 仅仅是对象调用方法,虽然创建了线程,但并未运行线程. for(int x = 0; x < 60; x++)
System.out.println("Hello World!====="+x);
}
}
 /*

 */
class FirstThread extends Thread
{
//private String name;
FirstThread(String name)
{
//this.name = name;
super(name);
}
public void run()
{
for(int i = 1; i <= 50; i++)
{
//System.out.println(this.name+"FirstThread run.====="+i);
System.out.println((Thread.currentThread()==this)+"......"+this.getName()+"FirstThread run.====="+i);
}
}
} class ThreadTest
{
public static void main(String args[])
{
FirstThread ft1 = new FirstThread("First===");
FirstThread ft2 = new FirstThread("Second===");
ft1.start();
ft2.start(); for(int i = 1; i <= 50; i++)
{
System.out.println("mainThread run.====="+i);
}
}
}
 /*
售票窗口例子:
多个窗口能够同时卖票.
*/ class Ticket extends Thread
{
private static int ticket = 100; //不用static时候.两个窗口都会同时卖同号的票,即100张票连个窗口都会卖一次(相当于卖了200次)
Ticket(String name)
{
super(name);
}
public void run()
{
while(true)
{
if(ticket>0)
{
System.out.println(Thread.currentThread().getName()+"===卖票===="+ticket--);
}
}
}
} class TicketDemo
{
public static void main(String args[])
{
Ticket t1 = new Ticket("窗口1");
Ticket t2 = new Ticket("窗口2");
t1.start();
t2.start(); }
}

线程的第二种方式:

实现Runnable接口:

格式为:

class MyRunnable implements Runnable

{

  public void run()

  {

     线程中要运行的有关代码.

  }

}

其步骤一般为:

1.定义一个类实现Runnable接口.

2.复写Runnable接口中的run方法.

3.通过Thread类来创建一个对象.

4.将Runnable的子类的对象作为实际参数传给Thread类中的构造函数.

5.调用Thread类中的start方法.开启线程,并调用Runnable接口的子类的run方法.(可以理解为run方法又start方法开启调用的)

例如:

class MyRunnable implements Runnable  //步骤1

{

  public void run()  //步骤2

  {

    S.o.p();

  }

}

class RunnableDemo

{

  p.s.v.main()

  {

    MyRunnable mr = new MyRunnable();

    Thread t1 = new Thread(mr);  //步骤3---4

    t1.start();    //步骤5

  }

}

 /*
售票窗口例子:
多个窗口能够同时卖票.
不使用静态的ticket来完成每个窗口的卖票,且不会卖重复的票.
通过实现Runnable接口来完成. 创建线程的第二种方法:
实现Runnable接口来完成.
步骤:
1.定义一个类实现(implements)Runnable接口
2.复写Runnable接口中的run方法
3.通过Thread类来创建对象
4.将Runnable接口的子类对象作为实际参数传给Thread类中的构造函数.
5.调用Thread类中的start方法开启线程,并调用Runnable接口的子类的run方法.
*/ class Ticket implements Runnable
{
private int ticket = 100; // private static int ticket = 100;
/*
由于Ticket并未继承Thread,该类并没有getName()的方法,因此是不能调用的.
Ticket(String name)
{
super(name);
}
*/
public void run()
{
while(true)
{
if(ticket>0)
{
System.out.println(Thread.currentThread().getName()+"===卖票====="+ticket--);
}
}
}
} class RunnableTicketDemo
{
public static void main(String args[])
{
Ticket t = new Ticket(); //t是共享数据. /*
下面的方法不静态ticket时候会出现卖了200张票的情况,如何不静态 ticket =100,也自定义线程名且不出现卖200张票的情况????
*/
//Ticket tt = new Ticket();
//Ticket ttt = new Ticket();
//Ticket tttt = new Ticket(); //Thread t1 = new Thread(t,"窗口1");
//Thread t2 = new Thread(tt,"窗口2");
//Thread t3 = new Thread(ttt,"窗口3");
//Thread t4 = new Thread(tttt,"窗口4");
/*
下面的代码执行后,Thread.currentThread().getName()获取的是默认的线程名.
*/
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();
}
}

继承方式和实现方式的多态的区别和特点:

实现方式:避免了单继承的局限性.一般定义线程时,建议使用实现方式.

区别:

1.继承Thread:线程代码存放在Thread的子类的run方法中.

2.实现Runnabel:线程的代码存放在Runnable接口的子类的run方法中.

最后是同步代码块,解决了多线程的安全性问题

格式为:

synchronized(对象)

{

需要被同步的代码块.

}

有关实现Runnable接口和同步的示例和练习代码:

 /*
多线程的安全问题;
打印出了票数为0.-1.-2等问题. 问题分析,多条语句同时使用同一线程的共享数据时,一个线程只执行了一部分,还未执行完,另一个线程就参与进来执行了,导致共享数据的错误.
在if判断中,当ticket=1时,一个线程进去执行语句后,另一个线程也执行进来.
此时的ticket已经通过ticket--变成了0,从而导致了输出票数为0或者负数的情况.
解决方案:
对操作多条共享数据的语句,让一个线程完全执行完毕后才让另一个线程执行,从而避免这种问题的发生. 同步代码块.关键字:synchronized
格式:
synchronized(对象)
{
需要被同步的代码.
{ 同步的条件:
1.必须是多线程,单线程不能用同步.
2.必须是多个线程使用同一个锁.
必须保证同步中只有一个线程在运行. 同步的好处:解决了多线程的安全性问题.
缺点:每个线程都要判断锁,影响程序运行速度,耗费资源.
*/
class Ticket implements Runnable
{
private int ticket = 100;
Object obj = new Object();
public void run()
{
while(true)
{
synchronized(obj) //obj相当于锁.
{
if(ticket>0)
{
// try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"===卖票====="+ticket--);
}
}
}
}
} class RunnableTicketSafeDemo
{
public static void main(String args[])
{
Ticket t = new Ticket(); //t是共享数据. 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();
}
}

Java基础笔记-多线程的更多相关文章

  1. Java基础技术多线程与并发面试【笔记】

    Java基础技术多线程与并发 什么是线程死锁? ​死锁是指两个或两个以上的进程(线程)在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去,我们就可以称 ...

  2. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  3. Java学习笔记-多线程-创建线程的方式

    创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...

  4. Java基础笔记 – Annotation注解的介绍和使用 自定义注解

    Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 |  被围观 25,969 views+ 1.Anno ...

  5. 【转】Java基础笔记 – 枚举类型的使用介绍和静态导入--不错

    原文网址:http://www.itzhai.com/java-based-notes-introduction-and-use-of-an-enumeration-type-static-impor ...

  6. 黑马程序员----java基础笔记中(毕向东)

    <p>------<a href="http://www.itheima.com" target="blank">Java培训.Andr ...

  7. 黑马程序员----java基础笔记上(毕向东)

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 笔记一共记录了毕向东的java基础的25天课程,分上.中.下 本片为上篇,涵盖前10天课程 1. ...

  8. Java基础之多线程篇(线程创建与终止、互斥、通信、本地变量)

    线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...

  9. [Java][读书笔记]多线程编程

    前言:最近复习java,发现一本很好的资料,<J​a​v​a​2​参​考​大​全​ ​(​第​五​版​)​> ​ ​H​e​r​b​e​r​t​.Schildt.书比较老了,06年的,一些 ...

随机推荐

  1. Oracle学习(十):视图,索引,序列号,同义词

    1.知识点:能够对比以下的录屏进行阅读 视图,序列,索引,同义词 SQL> --视图:虚表 SQL> --视图的长处:简化复杂查询.限制数据訪问(银行用的多).提供数据的相互独立.相同的数 ...

  2. socketpair的使用

    socketpair函数概要例如以下:#include <sys/types.h>#include <sys/socket.h>int socketpair(int domai ...

  3. putty保持连接不自动段开

    经常在网上看到有人说自己利用putty工具登录服务器总是连接不上,这样的情况自己在刚接触putty时也遇到过.在 Connection 里面有个 Seconds between keepaliaves ...

  4. 易语言转C#小试牛刀

    呵呵,用了几年的易语言,太郁闷了,玩过E的童鞋们懂得,偶然机会尝试C#,现正式投入C#门下. 我会把我学习C#的一些知识和重点,实时发不到我的BLOG中,同想学习C#的童鞋一起成长起来.

  5. W3C-XML

    XML XML Extensible Markup Language,可扩展标记语言 1 XML和HTML的区别 XML主要用来传输数据 HTML主要用来呈现数据内容 2 XML的主要用途 传输数据 ...

  6. PHP学习笔记一

    <html> <head> <title></title> <meta http-equiv="content-type" c ...

  7. 单链表(Single Linked List)

    链表的结点结构  ┌───┬───┐  │data|next│  └───┴───┘ data域--存放结点值的数据域 next域--存放结点的直接后继的地址(位置)的指针域(链域) 实例:从终端输入 ...

  8. sizeof 和 strlen

    1. sizeof 1.1 sizeof是一个独立的运算符,不是函数.sizeof给我们提供有关数据项目所分配的内存的大小.例如: 1 2 cout << sizeof(long) < ...

  9. SQL使用记录

    Q:怎么删掉sql server登录时的用户名?(仅仅是删掉那个登录时的提示) A:先关闭数据库登录引擎,然后删除:%AppData%\Microsoft\Microsoft SQL Server\1 ...

  10. 从汇编看c++成员函数指针(三)

    前面的从汇编看c++中成员函数指针(一)和从汇编看c++成员函数指针(二)讨论的要么是单一类,要么是普通的多重继承,没有讨论虚拟继承,下面就来看一看,当引入虚拟继承之后,成员函数指针会有什么变化. 下 ...