首页技术文章正文

多线程的总结与常见问题解析

更新时间:2018-11-26 来源:黑马程序员 浏览量:

  【创建多线程的第一种方式:--继承Thread类】

  1:定义一个类继承Thread类

  2:重写Thread类中的run方法

  3:创建该类的实例,并调用start方法。

  【start方法的作用】:A、启动线程。B、调用run方法

  1、模拟一个多线程:

  class MyThread extends Thread{

  public void run(){

  for(int i=1;i<500;i++){

  System.out.println("MyThread:"+i);

  }

  }

  }

  public class Demo1{

  public Static void main(String[] args){

  MyThread my = new MyThread();

  my.start();

  for(int j=1;j<500;j++){

  System.out.println("main:"+i);

  }

  }

  }

  2、匿名内部类的线程实现方式:

  public class Demo2{

  public static void main(String[] args){

  new Thread{

  public void run(){

  for(int=i;i<100;i++){

  System.out.println("MyThread:"=i);

  }

  }

  }.start;

  }

  for(int i=1;i<100;i++){

  System.out.println("main:"+i);

  }

  }

  3、模拟一个QQ聊天的线程:

  class Video extends Thread{

  public void run(){

  while(true){

  System.out.println("视频中...");

  }

  }

  }

  class Talk extends Thread{

  public void run(){

  while(true){

  System.out.println("聊天中...");

  }

  }

  }

  public class Demo3{

  public static void main(String[] args){

  Video v = new Video();

  Talk t = new Video();

  v.start();

  t.start();

  for(int i=1;i<100;i++){

  System.out.println("main:"+i);

  }

  }

  }

  -------------------------------------------------------------------------------------------------------

  【创建线程的第二种方式:--实现Runnable接口】

  1、实现Runnable接口

  2、重写Runnable接口中的run方法

  3、将Runnable接口中的子类对象作为实际参数,传递给Thread类的构造方法

  4、调用Thread类中的start方法开启线程

  1、public class Demo1{

  public static void main(String[] args){

  MyRun my = new MyRun();

  Thread t = new Thread(my);

  t.start();

  for(int i=1;i<100;i++){

  System.out.println("main:"+i);

  }

  }

  }

  class MyRun implements Runnable{

  public void run(){

  for(int i=1;i<100;i++){

  System.out.println("MyRun:"+i);

  }

  }

  }

  2、模拟卖票系统【实现Runnable接口】

  public class Demo{

  public static void main(String[] args){

  MyRunTick mt = new MyRunTick();

  Thread t1 = new Thread(mt,"一号窗口");

  Thread t2 = new Thread(mt,"二号窗口");

  Thread t3 = new Thread(mt,"三号窗口");

  Thread t4 = new Thread(mt,"四号窗口");

  t1.start();

  t2.start();

  t3.start();

  t4.start();

  }

  }

  class MyRunTicket implements Runnable{

  private int ticket = 100;

  public void run(){

  while(true){

  synchronized(this){

  if(ticket > 0){

  System.out.println(Thread.currentThread().getName()+"卖:"+this.ticket+"号票");

  try{

  Thread.sleep(1);

  }catch(InterruptedException e){

  e.printStackTrace();

  }

  ticket--;

  }else{

  System.out.println(Thread.currentThread().getName()+"票已卖完。。");

  break;

  }

  }

  }

  }

  }

  总结:同步的前提是必须有两个或者两个以上的线程,多个线程使用的是同一个锁。

  线程同步的前提:1、必须是多个线程使用同一个锁;

  2、必须保证同步中只能有一个线程在运行

  -------------------------------------------------------------------------------------------------------

  1、实现方式和继承方式有什么区别?

  实现的好处是:避免了单继承的局限性。---->> 定义线程的时候最好使用实现方式

  区别是:继承Thread线程的代码存放在Thread子类的run()方法中;

  实现Runnable线程的代码存放在接口子类的run()方法中。

  2、什么是锁对象?如何创建?如何获得?

  每个Java对象都有一个锁对象,而且只有一把钥匙;

  可以使用this关键字作为锁对象,也可以使用所在类的字节码文件对应的Class对象作为锁对象;

  可以通过:类名.class 或者 对象.Class() 获得。

  3、同步的使用?

  只能同步方法(代码块),不能同步类或者变量。

  4、如何解决《生产者与消费者》的问题?

  可以通过一个标记,表示数据的存储空间状态。

  【代码如下:】

  pulibc class Demo{

  public static void main(String[] args){

  Persion p = new Person();

  Producer pro = new Prodecer();

  Consumer con = new Consumer();

  Thread t1 = new Thread(pro,"生产者");

  Thread t2 = new Thread(con,"消费者");

  t1.start();

  t2.start();

  }

  }

  // 使用Person作为数据存储空间

  class Person{

  String name;

  String gender;

  boolean flag = false;

  public synchronized void set(String name,String gender){

  if(flag){

  try{

  wait();

  }catch(InterruptedException e){

  e.printStackTrace();

  }

  }

  this.name = name;

  this.gender = gender;

  flag = true;

  notify();

  }

  public synchronized void read(){

  if(!flag){

  try{

  wait();

  }catch(InterruptedException e){

  e.printStackTrace();

  }

  }

  System.out.println("name:"+this.name+"----gender:"+this.gender);

  flag = false;

  notify();

  }

  }

  // 生产者

  class Producer implements Runnable{

  Person p;

  public Producer(){

  }

  public Producer(Person p ){

  this.p = p;

  }

  public void run(){

  int i = 0;

  while(trues){

  if(i%2=0){

  p.set("jack","man");

  }else{

  p.set("小丽","女");

  }

  i++;

  }

  }

  }

  // 消费者

  class Consumer implements Runnable{

  Person p;

  public Consumer(){

  }

  public Consumer(Person p){

  this.p = p;

  }

  public void run(){

  while(true){

  p.read();

  }

  }

  }

  5、在Object类中,wait()和sleep()有什么却别?

  wait() 是Object中的方法,表示:释放资源,释放锁。

  sleep()是Thread中的方法,表示:释放资源,不释放锁。

  6、为什么定义了notify(),还要再定义notifyAll()?

  因为如果只用notify()的话,容易出现只唤醒本方线程的情况,导致程序中的所有线程都在等待。



作者:黑马程序员JavaEE培训学院

首发: http://java.itheima.com

分享到:
在线咨询 我要报名
和我们在线交谈!